一个非常有趣的使用spring框架AOP例子
Springboot纯注解Aop示例
![Springboot纯注解Aop示例](https://img.taocdn.com/s3/m/e47197fff021dd36a32d7375a417866fb84ac0c4.png)
Springboot纯注解Aop示例Spring Boot是一个基于Spring框架的快速开发框架,提供了一种简化Java应用程序开发和部署的方式。
AOP(Aspect-Oriented Programming)是一种面向切面编程的技术,可以通过在不改变原有代码的情况下,动态地将额外的逻辑横切到应用程序的各个模块中。
在Spring Boot中使用纯注解实现AOP,可以通过使用AspectJ注解来定义切面和通知,以及使用Spring AOP注解来实现横切逻辑的织入。
下面是一个示例,展示了如何在Spring Boot中使用注解实现AOP。
首先,我们需要在pom.xml文件中添加必要的依赖:```xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>``````javapublic class LoggingAspectpublic void controllerMethod}public void logMethodCall(JoinPoint joinPoint)String methodName = joinPoint.getSignature(.getName(;String className =joinPoint.getTarget(.getClass(.getSimpleName(;System.out.println("Calling method " + methodName + " of class " + className);}public void logMethodReturn(JoinPoint joinPoint, Object result)String methodName = joinPoint.getSignature(.getName(;String className =joinPoint.getTarget(.getClass(.getSimpleName(;System.out.println("Method " + methodName + " of class " + className + " returned " + result);}``````javapublic class SpringBootDemoApplicationpublic static void main(String[] args)}```现在,我们可以编写一个简单的Controller类来测试我们的AOP切面:```javapublic class GreetingControllerpublic String sayHellreturn "Hello, World!";}``````Calling method sayHello of class GreetingControllerMethod sayHello of class GreetingController returned Hello, World!```通过使用纯注解的方式,我们可以很方便地在Spring Boot应用程序中实现AOP功能。
SpringAOP的原理和应用场景
![SpringAOP的原理和应用场景](https://img.taocdn.com/s3/m/497e1d7fbf1e650e52ea551810a6f524ccbfcbea.png)
SpringAOP的原理和应用场景SpringAOP(Aspect-Oriented Programming)是Spring框架中的一个重要组成部分,它提供了一种通过预定义的方式,将横切关注点(Cross-cutting Concerns)与业务逻辑进行解耦的机制。
本文将介绍SpringAOP的原理及其在实际应用场景中的应用。
一、SpringAOP的原理SpringAOP基于代理模式(Proxy Pattern)实现。
在SpringAOP中,通过生成与原始类(被代理类)具有相同接口的代理类,将横切逻辑编织到业务逻辑中。
在运行时,当调用代理类的方法时,会在方法执行前、后或异常抛出时插入相应的横切逻辑代码。
具体而言,SpringAOP使用了以下几个核心概念:1. 切面(Aspect):切面是横切逻辑的模块化单元,它包含了一组通知(Advice)和切点(Pointcut)。
2. 通知(Advice):通知定义了实际的横切逻辑代码,并规定了何时执行该代码。
SpringAOP提供了五种类型的通知:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。
3. 切点(Pointcut):切点指定了在哪些连接点(Join Point)上执行通知。
连接点可以是方法调用、属性访问等程序执行的点。
4. 连接点(Join Point):连接点是程序执行过程中的一个特定点,如方法调用前、方法调用后等。
通知通过切点来选择连接点。
5. 织入(Weaving):织入是将切面应用到目标对象,并创建代理对象的过程。
织入可以在编译时、类加载时或运行时进行。
二、SpringAOP的应用场景SpringAOP可应用于各种场景,用于解决跨越多个模块或类的横切关注点问题。
以下是一些常见的SpringAOP应用场景:1. 日志记录:通过在关键方法的前后插入日志代码,实现对系统运行状态的监控和记录。
SpringBootAop详解和多种使用场景
![SpringBootAop详解和多种使用场景](https://img.taocdn.com/s3/m/c4eefece2dc58bd63186bceb19e8b8f67c1cefc2.png)
SpringBootAop详解和多种使⽤场景前⾔aop⾯向切⾯编程,是编程中⼀个很重要的思想本篇⽂章主要介绍的是SpringBoot切⾯Aop的使⽤和案例什么是aopAOP(Aspect OrientedProgramming):⾯向切⾯编程,⾯向切⾯编程(也叫⾯向⽅⾯编程),是⽬前软件开发中的⼀个热点,也是Spring框架中的⼀个重要内容。
利⽤AOP可以对业务逻辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼程序的可重⽤性,同时提⾼了开发的效率。
使⽤场景利⽤AOP可以对我们边缘业务进⾏隔离,降低⽆关业务逻辑耦合性。
提⾼程序的可重⽤性,同时提⾼了开发的效率。
⼀般⽤于⽇志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理。
使⽤场景为什么需要⾯向切⾯编程⾯向对象编程(OOP)的好处是显⽽易见的,缺点也同样明显。
当需要为多个不具有继承关系的对象添加⼀个公共的⽅法的时候,例如⽇志记录、性能监控等,如果采⽤⾯向对象编程的⽅法,需要在每个对象⾥⾯都添加相同的⽅法,这样就产⽣了较⼤的重复⼯作量和⼤量的重复代码,不利于维护。
⾯向切⾯编程(AOP)是⾯向对象编程的补充,简单来说就是统⼀处理某⼀“切⾯”的问题的编程思想。
如果使⽤AOP的⽅式进⾏⽇志的记录和处理,所有的⽇志代码都集中于⼀处,不需要再每个⽅法⾥⾯都去添加,极⼤减少了重复代码。
技术要点通知(Advice)包含了需要⽤于多个应⽤对象的横切⾏为,完全听不懂,没关系,通俗⼀点说就是定义了“什么时候”和“做什么”。
连接点(Join Point)是程序执⾏过程中能够应⽤通知的所有点。
切点(Poincut)是定义了在“什么地⽅”进⾏切⼊,哪些连接点会得到通知。
显然,切点⼀定是连接点。
切⾯(Aspect)是通知和切点的结合。
通知和切点共同定义了切⾯的全部内容——是什么,何时,何地完成功能。
引⼊(Introduction)允许我们向现有的类中添加新⽅法或者属性。
SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。
![SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。](https://img.taocdn.com/s3/m/7fec2d0bbfd5b9f3f90f76c66137ee06eef94e50.png)
SpringAOP⽰例与实现原理总结——传统springaop、基于切⾯注⼊、基于@Asp。
⼀、代码实践1)经典的Spring Aop经典的spring aop,是基于动态代理技术的。
实现⽅式上,最常⽤的是实现MethodInterceptor接⼝来提供环绕通知,创建若⼲代理,然后使⽤ProxyBeanFactory配置⼯⼚bean,⽣成拦截器链,完成拦截。
⽰例如下:1package demo.spring;23import org.aopalliance.intercept.MethodInterceptor;4import org.aopalliance.intercept.MethodInvocation;5import org.junit.Test;6import org.junit.runner.RunWith;7import org.springframework.beans.factory.annotation.Autowired;8import org.springframework.test.context.ContextConfiguration;9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;1011 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration("classpath:spring-config.xml")13public class TraditionalSpringAopDemo {14 @Autowired15private Service proxy;1617 @Test18public void test() {19 proxy.execute("hello world!");20 }21 }2223interface Service {24void execute(String str);25 }2627class ServiceImpl implements Service {28 @Override29public void execute(String str) {30 System.out.println("execute invoke: " + str);31 }32 }3334class Interceptor1 implements MethodInterceptor {35 @Override36public Object invoke(MethodInvocation methodInvocation) throws Throwable {37 System.out.println("interceptor1,before invoke");38 Object ret = methodInvocation.proceed();39 System.out.println("interceptor1,after invoke");40return ret;41 }42 }4344class Interceptor2 implements MethodInterceptor {45 @Override46public Object invoke(MethodInvocation methodInvocation) throws Throwable {47 System.out.println("interceptor2,before invoke");48 Object ret = methodInvocation.proceed();49 System.out.println("interceptor2,after invoke");50return ret;51 }52 }xml⽂件配置:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:context="/schema/context"5 xmlns:aop="/schema/aop"6 xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/sprin 78<context:component-scan base-package="demo.spring"/>910<bean class="demo.spring.ServiceImpl" id="service"></bean>11<bean class="demo.spring.Interceptor1" id="interceptor1"></bean>12<bean class="demo.spring.Interceptor2" id="interceptor2"></bean>13<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy">14<property name="target" ref="service"/>15<property name="interceptorNames">16<list>17<value>interceptor1</value>18<value>interceptor2</value>19</list>20</property>21</bean>22</beans>结果:interceptor1,before invokeinterceptor2,before invokeexecute invoke: hello world!interceptor2,after invokeinterceptor1,after invoke可以看到拦截链的执⾏过程与拦截器顺序的关系。
Spring之注解实现aop(面向切面编程)
![Spring之注解实现aop(面向切面编程)](https://img.taocdn.com/s3/m/ea36e41211a6f524ccbff121dd36a32d7375c7b6.png)
Spring之注解实现aop(⾯向切⾯编程)1:Aop(aspect object programming)⾯向切⾯编程,名词解释:1.1:功能:让关注点代码与业务逻辑代码分离1.2:关注点重复代码就叫做关注点1.3:切⾯关注点形成的类,就叫做切⾯(类)⾯向切⾯编程,就是指对很多功能都有的重复代码抽取,再在运⾏的时候往业务⽅法上动态植⼊"切⾯类代码";1.4:切⼊点执⾏⽬标对象⽅法,动态植⼊切⾯代码可以通过切⼊点表达式,指定拦截那些类的那些⽅法,给指定的类在运⾏的时候植⼊切⾯类代码;2:注解⽅式实现aop编程2.1:开发步骤(1):先引⼊aop相关的jar⽂件spring-aop-3.2.5.RELEASE.jar【去spring3.2源码⾥⾯找】aopalliance.jar【去spring2.5源码/lib/aopalliance⽂件⾥⾯找】aspectjweaver.jar【去spring2.5源码/lib/aspectj⽂件⾥⾯找】或者【aspectj-1.8.2/lib/aspectjweaver.jar】aspectjrt.jar【去spring2.5源码/lib/aspectj⽂件⾥⾯找】或者【aspectj-1.8.2/lib/aspectjrt.jar】 《注意:⽤到的spring2.5版本的jar本舰,如果⽤jd1.7版本可能会出现问题,需要升级以下aspectj组件,即使⽤aspectj-1.8.2版本中提供的jar⽂件aspectjweaver.jar和aspectjrt.jar》(2)bean.xml中引⼊aop名称空间 技巧:找到⽂件spring-framework-3.2.5.RELEASE/docs/spring-framework-reference/htmlsingle 打开index.html搜索xmlns:aop然后找到下⾯红⾊三句话,分别拷贝到bean.xml中 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="/schema/beans" xmlns:xsi="/2001/XMLSchema-instance" xmlns:aop="/schema/aop" xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/aop /schema/aop/spring-aop.xsd"> 拷贝之后的bean.xml如下所⽰:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:p="/schema/p"5 xmlns:context="/schema/context"6 xmlns:aop="/schema/aop"7 xsi:schemaLocation="8 /schema/beans9 /schema/beans/spring-beans.xsd10 /schema/context11 /schema/context/spring-context.xsd12 /schema/aop13 /schema/aop/spring-aop.xsd">1415</beans> (3):bean.xml中开启aop注解扫描,如下配置所⽰:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:p="/schema/p"5 xmlns:context="/schema/context"6 xmlns:aop="/schema/aop"7 xsi:schemaLocation="8 /schema/beans9 /schema/beans/spring-beans.xsd10 /schema/context11 /schema/context/spring-context.xsd12 /schema/aop13 /schema/aop/spring-aop.xsd">1415<!-- 开启注解扫描 -->16<context:component-scan base-package="com.bie.aop"></context:component-scan>1718<!-- 开启aop注解⽅式,默认为false -->19<aop:aspectj-autoproxy></aop:aspectj-autoproxy>2021</beans> (4):开始写⼀个切⾯类,源码如下所⽰:1package com.bie.aop;23import ng.annotation.After;4import ng.annotation.Aspect;5import ng.annotation.Before;6import ng.annotation.Pointcut;7import ponent;8910/**11* @author BieHongLi12* @version创建时间:2017年3⽉28⽇下午9:10:4313* @Aspect:指定当前类为切⾯类14*/15 @Component //加⼊到IoC容器16 @Aspect //指定当前类为切⾯类17public class Aop {1819//指定切⼊点表达式,拦截那些⽅法,即为那些类⽣成代理对象20//@Pointcut("execution(* erDao.save(..))") ..代表所有参数21//@Pointcut("execution(* erDao.*())") 指定所有的⽅法22//@Pointcut("execution(* erDao.save())") 指定save⽅法2324 @Pointcut("execution(* erDao.*(..))")25public void pointCut(){2627 }2829 @Before("pointCut()")30public void begin(){31 System.out.println("开启事务");32 }3334 @After("pointCut()")35public void close(){36 System.out.println("关闭事务");37 }3839 } (5):写好切⾯类就可以写执⾏⽬标对象⽅法,接⼝和实现类如下所⽰: 1package com.bie.aop;23/**4* @author BieHongLi5* @version创建时间:2017年3⽉28⽇下午9:09:296*7*/89public interface IUserDao {1011public void save();12 }1package com.bie.aop;234import ponent;56/**7* @author BieHongLi8* @version创建时间:2017年3⽉28⽇下午9:09:539* ⽬标对象10*/11 @Component12public class UserDao implements IUserDao{1314 @Override15public void save() {16 System.out.println("..核⼼业务--核⼼业务..");17 }181920 } (6):最后就可以进⾏进⾏测试了,源码如下所⽰:1package com.bie.aop;23import org.junit.Test;4import org.springframework.context.ApplicationContext;5import org.springframework.context.support.ClassPathXmlApplicationContext;67/**8* @author BieHongLi9* @version创建时间:2017年3⽉28⽇下午9:13:1810*11*/12public class AopTest {1314 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");1516//⽬标对象有实现接⼝,spring会⾃动选择"jdk代理【动态代理】"17//动态代理的标识:class com.sun.proxy.$Proxy1018 @Test19public void test01(){20 IUserDao dao = (IUserDao) ac.getBean("userDao");21 System.out.println(dao.getClass());22 dao.save();23 }242526//class com.bie.aop.OrderDao$$EnhancerByCGLIB$$4952a60a27//⽬标对象没有实现接⼝,spring会⽤"cglib代理哦"28 @Test29public void testCglib(){30 OrderDao dao = (OrderDao) ac.getBean("orderDao");31 System.out.println(dao.getClass());32 dao.save();33 }34 } 3:⼼得体会和报错解决: 3.1:虽然案例很简单很简单,但是我花了三四个⼩时,为什么呢!我⽤junit测试spring写的注解实现aop(⾯向切⾯编程)。
AOP-2实例(SpringBoot注解方式)
![AOP-2实例(SpringBoot注解方式)](https://img.taocdn.com/s3/m/e8ccc25668eae009581b6bd97f1922791688be83.png)
AOP-2实例(SpringBoot注解⽅式) 1、创建Spring Boot项⽬ 创建⼀个Spring Boot 项⽬,然后pom中引⼊web 模块与AOP相关依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.0.1.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version></dependency>其中:aspectjweaver是与aspectj相关的包,⽤来⽀持切⾯编程的;aspectjweaver是aspectj的织⼊包;2、实现⼀个web请求,数据通过接⼝获取(使⽤POJO类传参与返回值)@RestController@RequestMapping("/aop")public class AopController {@Autowiredprivate AopService aopService;@GetMapping(value = "getResult")public ResultVO sayHello(ParamVO paramVO) {ParamDTO paramDTO = new ParamDTO();BeanUtils.copyProperties(paramVO, paramDTO);ResultDTO resultDTO = aopService.getResult(paramDTO);ResultVO resultVO = new ResultVO();BeanUtils.copyProperties(resultDTO, resultVO);return resultVO;}}列出⼀个POJO类,其他类似。
spring基于注解配置aop案例
![spring基于注解配置aop案例](https://img.taocdn.com/s3/m/5de70007591b6bd97f192279168884868762b84d.png)
spring基于注解配置aop案例spring基于注解配置aop案例1、导⼊jar包基于maven项⽬<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.14</version></dependency>2、编写实体类package com.yl.bean;import java.io.Serializable;/*** ⽤户实体类*/public class User implements Serializable {private Integer id;private String username;private String password;public User() {}public User(Integer id, String username, String password) {this.id = id;ername = username;this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {ername = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}}3、编写业务层业务层接⼝package com.yl.service;/*** ⽤户业务层接⼝*/public interface IUserService {/*** 查询⽤户*/public void queryUser();}业务层接⼝实现类package com.yl.service.impl;import com.yl.dao.IUserDao;import com.yl.service.IUserService;import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** ⽤户业务层接⼝实现类*/@Service("userService")public class IUserServiceImpl implements IUserService { @Resource(name = "userDao")private IUserDao iUserDao;//⽤户持久层对象/*** 查询⽤户*/@Overridepublic void queryUser() {// int i=1/0;iUserDao.queryUser();}}4、编写持久层持久层接⼝package com.yl.dao;/*** ⽤户持久层接⼝*/public interface IUserDao {/*** 查询⽤户*/public void queryUser();}持久层接⼝实现类package com.yl.dao.impl;import com.yl.dao.IUserDao;import org.springframework.stereotype.Repository;/*** ⽤户持久层接⼝实现类*/@Repository("userDao")public class IUserDaoImpl implements IUserDao {/*** 查询⽤户*/@Overridepublic void queryUser() {System.out.println("查询成功");}}5、编写通知类package rm;import ng.ProceedingJoinPoint;import ng.annotation.*;import ponent;/*** spring通知类*/@Component("userInform")@Aspect//指定当前类为切⾯public class UserInform {/***配置通⽤切⼊点*/@Pointcut("execution(* com.yl.service.impl.IUserServiceImpl.*())")private void pt1(){}/*** 前置通知*/@Before("pt1()")public void beforeInform(){System.out.println("开启事务");}/*** 后置通知*/@AfterReturning("execution(* com.yl.service.impl.IUserServiceImpl.*())")public void afterInform(){System.out.println("提交事务");}/*** 异常通知*/@AfterThrowing("execution(* com.yl.service.impl.IUserServiceImpl.*())")public void throwInform(){System.out.println("异常通知");}/*** 环绕通知*//*public void aroundInform(ProceedingJoinPoint pjp){System.out.println("前置通知");try {pjp.proceed();System.out.println("后置通知");} catch (Throwable throwable) {System.out.println("异常通知");}finally {System.out.println("最终通知");}}*/}6、配置⽂件<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:aop="/schema/aop"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd/schema/aop/schema/aop/spring-aop.xsd/schema/contexthttps:///schema/context/spring-context.xsd"><!--指定spring要扫描的包--><context:component-scan base-package="com.yl"></context:component-scan> <!--开启spring对注解aop的⽀持--><aop:aspectj-autoproxy/></beans>7、测试package com.yl.ui;import com.yl.service.IUserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 测试类*/public class MainTest {public static void main(String[] args) {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml"); IUserService userService= (IUserService) applicationContext.getBean("userService");userService.queryUser();}}8、不使⽤xml⽅式⽤配置类替代xml配置⽂件@Configuration@ComponentScan(basePackages="com.itheima")@EnableAspectJAutoProxypublic class SpringConfiguration {}。
应用Spring框架中的AOP Arround类型的通知组件实现监控项目性能的应用实例
![应用Spring框架中的AOP Arround类型的通知组件实现监控项目性能的应用实例](https://img.taocdn.com/s3/m/5c2f7ab0f524ccbff1218448.png)
userPassWord=?";
try{
try {
java.sql.PreparedStatement
pstmt
=
con.prepareStatement(select_SqlStatement,
杨教授工作室,版权所有,盗版必究, 1/6 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
oneUserInfoPOReturn.setUserPassWord(rs.getString("userPassWord"));
}
catch (SQLException e){
System.out.println(e.getMessage());
}
}
finally{
try {
con.close();
System.out.println("方法执行所花费的时间为"+usedTime+"秒");
Spring:SpringAop配合自定义注解实现切面编程
![Spring:SpringAop配合自定义注解实现切面编程](https://img.taocdn.com/s3/m/2feb1ed6ab00b52acfc789eb172ded630b1c9867.png)
Spring:SpringAop配合⾃定义注解实现切⾯编程此⽂章只作为笔记记录,不作为讲解⽂章。
1. SpringAop简介传统的OOP开发中的代码逻辑是⾃上⽽下的,⽽这些过程会产⽣⼀些横切性问题,这些横切性的问题和我们的主业务逻辑关系不⼤,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。
AOP是处理⼀些横切性问题,AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的⽬的。
SpringAop的应⽤场景⽇志记录权限验证效率检查事务管理exception2. 依赖包引⼊//SpringBoot项⽬引⼊Aop依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.1.5.RELEASE</version></dependency>//Spring项⽬引⼊Aop依赖<!-- springAop依赖包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.2.4.RELEASE</version></dependency><!-- springAop依赖Aspect的语法标准包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.7.RELEASE</version></dependency>3. Aop实现⽰例项⽬结构3.1 定义依赖注⼊扫描器AppConfig配置类package com.java.study.config;import ponentScan;import org.springframework.context.annotation.EnableAspectJAutoProxy;//扫描注解@ComponentScan("com.java.study")//开启Aop,默认为false(JDK代理模式) true(Cglib模式)// (this) JDK代理时,指向接⼝和代理类proxy,cglib代理时指向接⼝和⼦类(不使⽤proxy)@EnableAspectJAutoProxy(proxyTargetClass = true)public class AppConfig {}3.2 ⾃定义service⽅法TestService测试⽅法类package com.java.study.service;import ponent;@Component("testService")public class TestService {public void Test1(){System.out.println("这是测试⽅法 test1 ......");}}3.3 定义切⾯类TestAdvice切⾯类package com.java.study.aspect;import com.java.study.custom.KthLog;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.*;import ponent;import java.util.logging.Logger;@Component@Aspectpublic class TestAdvice {private final static Logger logger = Logger.getLogger("TestAdvice.class");// @annotation匹配的是⾃定义注解所标注的⽅法@Pointcut("@annotation(com.java.study.custom.KthLog)")public void loggerMother(){}@Pointcut("execution(* com.java.study..*())")public void loggerMother2(){}@Pointcut("execution(* com.java.study.*(ng.String))")public void loggerMother3(){}@Before("loggerMother() && @within(log)")public void Before(JoinPoint pointcut, KthLog log){System.out.println(" ⽅法名:"+ pointcut.getSignature().getName() +"⽇志输出:"+log.value());}@After("loggerMother2()")public void Before(){System.out.println(" 测试增强⽅法。
一个Spring框架的例子
![一个Spring框架的例子](https://img.taocdn.com/s3/m/ac681efd941ea76e58fa0493.png)
一个spring框架的AOP例子接触spring有一段时间了,不过都是看的多,写的少,工作忙,公司也不准备用。
自己写过一些小东西用到,也只用到了BeanFactory组装对象,JdbcTemplate 代替jdbc,事务管理。
东抓一把,西抓一把,没形成系统。
最近也在看spring自带的reference,一时手痒,写了个AOP的创建advice的例子,比之单纯地使用TransationProxyFactoryBean 对AOP的理解又深入了点,打算看看它的源代码,基于CGLIB的实现对类的代理不了解,倒是好奇它如何实现对接口的代理——也就是利用J2SE的动态代理技术。
例子如下:讲述一间书店开始打折促销,规则是每一名顾客只能买一本书,而且<spring in action>已经脱销了。
你可以去掉TestAdvice里的注释看看各种运行结果,具体就不解释咯,在代码注释里。
首先,你必须对增强(advice)有所了解,增强就是在特定连接点执行的动作。
advice contains the logic of your aspect。
增强,分为4类:前增强(before) 在连接点之前调用后增强(after) 在连接点执行之后调用、环绕增强(around) 完整控制整个方法流程,必须调用MethodInvocation的proceed促使真实操作发生异常增强针对某个异常抛出时调用书店,一个buyBook业务:package com.denny_blue.springdemo.aop;public interface BuyBook {public void buyBook(String customer,String book)throws NoThisBookException;}实现此接口的一个业务对象,如果顾客要买<spring in action>就抛出NoThisBookException异常。
spring_aop例子1
![spring_aop例子1](https://img.taocdn.com/s3/m/f37abfcfd5bbfd0a795673cd.png)
一个简单的Spring的AOP例子这篇文章是我在别人博客上复制下来的,用于理解spring的aop是一个不错的例子(只用的spring,不含其它插件,但是配置比较麻烦,只做理解)在这个简单AOP例子中,包括前置通知,后置通知,环绕通知,和目标对象。
写这个例子的主要目标只是想让想学AOP的能更快地入门,了解一下如何去配置AOP里面的东东。
目标对象的接口:IStudent.java1/**2 *3*/4package com.dragon.study;56/**7 * @author dragon8 *9*/10public interface IStudent {1112public void addStudent(String name);13}14目标类:StudentImpl.java1/**2 *3*/4package com.dragon.study.Impl;6import com.dragon.study.IStudent;78/**9 * @author dragon10 *11*/12public class StudentImpl implements IStudent{1314public void addStudent(String name){15 System.out.println("欢迎"+name+"你加入Spring家庭!");16 }17}18前置通知:BeforeAdvice.java1/**2 *3*/4package com.dragon.Advice;56import ng.reflect.Method;78import org.springframework.aop.MethodBeforeAdvice;910/**11 * @author dragon13*/14public class BeforeAdvice implements MethodBeforeAdvice{1516public void before(Method method,Object[] args, Object target)17throws Throwable{1819 System.out.println("这是BeforeAdvice类的before方法.");2021 }22}23后置通知:AfterAdvice.java1/**2 *3 */4package com.dragon.Advice;56import ng.reflect.Method;78import org.springframework.aop.AfterReturningAdvice;910/**11 * @author dragon12 *13 */14public class AfterAdvice implements AfterReturningAdvice{1516public void afterReturning(Object returnValue ,Method method,17 Object[] args,Object target) throws Throwable{18 System.out.println("这是AfterAdvice类的afterReturning方法.");19 }202122}23环绕通知:CompareInterceptor.java1/**2 *3 */4package com.dragon.Advice;56import org.aopalliance.intercept.MethodInterceptor;7import org.aopalliance.intercept.MethodInvocation;8910/**11 * @author dragon12 *13 */14public class CompareInterceptor implements MethodInterceptor{1516public Object invoke(MethodInvocation invocation) throws Throwable{17 Object result = null;18 String stu_name = invocation.getArguments()[0].toString();19if ( stu_name.equals("dragon")){20//如果学生是dragon时,执行目标方法,21 result= invocation.proceed();2223 } else{24 System.out.println("此学生是"+stu_name+"而不是dragon,不批准其加入. ");25 }2627return result;28 }29}30配置文件applicationContext.xml1<?xml version="1.0" encoding="UTF-8"?>2<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springfr /dtd/spring-beans.dtd">34<beans>56<bean id="beforeAdvice" class="com.dragon.Advice.BeforeAdvice"></bean>7<bean id="afterAdvice" class="com.dragon.Advice.AfterAdvice"></bean>8<bean id="compareInterceptor" class="pareIntercept or"></bean>9<bean id="studenttarget" class="com.dragon.study.Impl.StudentImpl"></be an>1011<bean id="student" class="org.springframework.aop.framework.ProxyFactor yBean">12<property name="proxyInterfaces">13<value>com.dragon.study.IStudent</value>14</property>15<property name="interceptorNames">16<list>17<value>beforeAdvice</value>18<value>afterAdvice</value>19<value>compareInterceptor</value>20</list>21</property>22<property name="target">23<ref bean="studenttarget"/>24</property>2526</bean>2728293031</beans>现在开始写测试类,Test.java1/**2 *3 */4package com;56import org.springframework.context.ApplicationContext;7import org.springframework.context.support.FileSystemXmlApplicationContext;89import com.dragon.study.IStudent;1011/**12 * @author dragon13 *14 */15public class Test {1617/**18 * @param args19 */20public static void main(String[] args) {21// TODO Auto-generated method stub22 ApplicationContext ctx =23new FileSystemXmlApplicationContext("/com/dragon/applicationConte xt.xml");2425 IStudent person = (IStudent)ctx.getBean("student");26 person.addStudent("dragon");2728// person.addStudent("javadragon");29 }3031}32。
SpringAop实例@Aspect、@Before、@AfterReturning@Ar。。。
![SpringAop实例@Aspect、@Before、@AfterReturning@Ar。。。](https://img.taocdn.com/s3/m/7fcc18607ed5360cba1aa8114431b90d6c85892e.png)
SpringAop实例@Aspect、@Before、@AfterReturning@Ar。
⽤过spring框架进⾏开发的⼈,多多少少会使⽤过它的AOP功能,都知道有@Before、@Around和@After等advice。
最近,为了实现项⽬中的输出⽇志和权限控制这两个需求,我也使⽤到了AOP功能。
我使⽤到了@Before、@Around这两个advice。
但在,使⽤过程中,却对它们的执⾏顺序并不清楚。
为了弄清楚在不同情况下,这些advice到底是以怎么样的⼀个顺序进⾏执⾏的,我作了个测试,在此将其记录下来,以供以后查看。
前提对于AOP相关类(aspect、pointcut等)的概念,本⽂不作说明。
对于如何让spring框架扫描到AOP,本⽂也不作说明。
情况⼀: ⼀个⽅法只被⼀个Aspect类拦截当⼀个⽅法只被⼀个Aspect拦截时,这个Aspect中的不同advice是按照怎样的顺序进⾏执⾏的呢?请看:添加 PointCut类该pointcut⽤来拦截test包下的所有类中的所有⽅法。
package test;import ng.annotation.Pointcut;public class PointCuts {@Pointcut(value = "within(test.*)")public void aopDemo() {}}package test; import ng.annotation.Pointcut; public class PointCuts { @Pointcut(value= "within(test.*)") public void aopDemo() { } }添加Aspect类该类中的advice将会⽤到上⾯的pointcut,使⽤⽅法请看各个advice的value属性。
package test;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.*;import ponent;@Component@Aspectpublic class Aspect1 {@Before(value = "test.PointCuts.aopDemo()")public void before(JoinPoint joinPoint) {System.out.println("[Aspect1] before advise");}@Around(value = "test.PointCuts.aopDemo()")public void around(ProceedingJoinPoint pjp) throws Throwable{System.out.println("[Aspect1] around advise 1");pjp.proceed();System.out.println("[Aspect1] around advise2");}@AfterReturning(value = "test.PointCuts.aopDemo()")public void afterReturning(JoinPoint joinPoint) {System.out.println("[Aspect1] afterReturning advise");}@AfterThrowing(value = "test.PointCuts.aopDemo()")public void afterThrowing(JoinPoint joinPoint) {System.out.println("[Aspect1] afterThrowing advise");}@After(value = "test.PointCuts.aopDemo()")public void after(JoinPoint joinPoint) {System.out.println("[Aspect1] after advise");}}添加测试⽤Controller添加⼀个⽤于测试的controller,这个controller中只有⼀个⽅法,但是它会根据参数值的不同,会作出不同的处理:⼀种是正常返回⼀个对象,⼀种是抛出异常(因为我们要测试@AfterThrowing这个advice)package test;import test.exception.TestException;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping(value = "/aop")public class AopTestController {@ResponseStatus(HttpStatus.OK)@RequestMapping(value = "/test", method = RequestMethod.GET)public Result test(@RequestParam boolean throwException) {// case 1if (throwException) {System.out.println("throw an exception");throw new TestException("mock a server exception");}// case 2System.out.println("test OK");return new Result() {{this.setId(111);this.setName("mock a Result");}};}public static class Result {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) { = name;}}}测试正常情况在浏览器直接输⼊以下的URL,回车:http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false我们会看到输出的结果是:[Aspect1] around advise 1[Aspect1] before advisetest OK[Aspect1] around advise2[Aspect1] after advise[Aspect1] afterReturning advise测试异常情况在浏览器中直接输⼊以下的URL,回车:http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true我们会看到输出的结果是:1.[Aspect1] around advise 12.[Aspect1] before advise3.throw an exception4.[Aspect1] after advise5.[Aspect1] afterThrowing advise结论在⼀个⽅法只被⼀个aspect类拦截时,aspect类内部的 advice 将按照以下的顺序进⾏执⾏:正常情况:情况⼆: 同⼀个⽅法被多个Aspect类拦截此处举例为被两个aspect类拦截。
讲解Java的Spring框架中的AOP实现
![讲解Java的Spring框架中的AOP实现](https://img.taocdn.com/s3/m/f6b02e7ecbaedd3383c4bb4cf7ec4afe04a1b102.png)
讲解Java的Spring框架中的AOP实现讲解Java的Spring框架中的AOP实现简介面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。
除了类(classes)以外,AOP提供了切面。
切面对关注点进行模块化,例如横切多个类型和对象的事务管理。
(这些关注点术语通常称作横切(crosscutting)关注点。
)Spring的一个关键的组件就是AOP框架。
尽管如此,Spring IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring IoC容器更加完善。
Spring 2.0 AOP:Spring 2.0 引入了一种更加简单并且更强大的方式来自定义切面,用户可以选择使用基于模式(schema-based)的方式或者使用@AspectJ注解。
对于新的应用程序,如果用户使用Java 5开发,我们推荐用户使用@AspectJ风格,否则可以使用基于模式的风格。
这两种风格都完全支持通知(Advice)类型和AspectJ的.切入点语言,虽然实际上仍然使用Spring AOP进行织入(Weaving)。
本章主要讨论Spring 2.0对基于模式和基于@AspectJ的AOP支持。
Spring 2.0完全保留了对Spring 1.2的向下兼容性,下一章将讨论Spring 1.2 API所提供的底层的AOP支持。
Spring中所使用的AOP:提供声明式企业服务,特别是为了替代EJB声明式服务。
最重要的服务是声明性事务管理(declarative transaction management),这个服务建立在Spring的抽象事务管理(transaction abstraction)之上。
允许用户实现自定义的切面,用AOP来完善OOP的使用。
实例我们经常会用到的有如下几种1、基于代理的AOP2、纯简单java对象切面3、@Aspect注解形式的4、注入形式的Aspcet切面下面我们就一个一个来应用吧.下面先写一下几个基本的类。
springaop的原理及常见应用
![springaop的原理及常见应用](https://img.taocdn.com/s3/m/665706875ebfc77da26925c52cc58bd6318693ab.png)
Spring AOP的原理及常见应用概述Spring AOP(Aspect-Oriented Programming)是一种面向切面编程的技术,可以在应用的不同层次上定义和管理软件系统的横切关注点。
它通过在不修改原有代码的情况下,向往常的业务流程中插入额外的行为逻辑,从而达到对系统进行功能增强或横切逻辑的复用。
原理Spring AOP的原理基于动态代理技术和反射机制。
它通过运行时创建代理对象,将切面逻辑织入到目标对象中,在目标对象的方法执行前、后或异常时执行切面代码,实现额外的行为。
Spring AOP主要通过以下两种方式来实现切面逻辑的织入:1. 基于动态代理:使用JDK动态代理或CGLIB来生成代理对象,并将切面逻辑织入到代理对象中。
2. 基于字节码提前增强:通过继承或重写目标方法的方式,在目标类加载时,通过工具将切面逻辑编织入字节码中。
常见应用Spring AOP提供了一种简洁灵活的方式来应用切面逻辑,常见的应用包括:1. 日志记录通过切面逻辑,在方法执行前后记录日志信息,可以帮助我们追踪应用的执行流程,以及定位潜在的问题。
2. 安全校验在方法执行前进行身份认证和权限校验,确保只有授权用户才能访问敏感操作或受限资源。
3. 事务管理通过在方法执行前后进行事务开启、提交、回滚操作,可以保证数据库操作的一致性和可靠性。
4. 缓存处理在方法执行前先查询缓存,如果有缓存则直接返回结果,避免了不必要的数据库查询,提高系统性能。
5. 异常处理通过捕获方法执行过程中的异常,并进行统一处理,可以实现全局的异常日志记录、错误信息转换等。
6. 性能监控在方法执行前后记录方法的执行时间,并统计次数,从而对系统的性能进行监控和分析。
7. 限流熔断通过在方法执行前进行限流计数和熔断措施,可以保护系统免受恶意攻击或突发高并发请求的影响。
8. 动态路由通过切面逻辑实现动态的路由策略,可以根据业务需要将请求转发到不同的服务实例或集群。
Springaop(实验写法)
![Springaop(实验写法)](https://img.taocdn.com/s3/m/0da9ef0dfbd6195f312b3169a45177232f60e420.png)
Springaop(实验写法)1. 创建通知:定义⼀个接⼝Public interface Sleepable{voidsleep();}然后写⼀个Human类,他实现了这个接⼝publicHuman implements Sleepable{public void sleep(){ System.out.println("睡觉中...!"); }}2.编写⼀个SleepHelper类,它⾥⾯包含了睡觉的辅助⼯作,⽤AOP术语来说它就应该是通知Public class Sleep Helper implements MethodBeforeAdvice,AfterReturningAdvice {publicvoidbefore(Method method, Object[] arguments, Object target)throwsThrowable {System.out.println("睡觉前");}publicvoidafterReturning(Object rturnValue, Method method, Object[] arguments, Object target)throwsThrowable {System.out.println("睡觉后");}}然后在spring配置⽂件中进⾏配置:<!-- 被代理⽬标对象 --><bean id="Human"class="cn.happy.dao.Human"></bean><bean id="SleepHelper"class="cn.happy.aop.SleepHelper"></bean>//定义切点的常⽤的两种⽅式:1)使⽤正则表达式 2)使⽤AspectJ表达式,//这⾥⽤正则表达式<!-- 顾问 --> <bean id="BeforAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property name="advice" ref="BeforAdvice"></property> <property name="pattern" value=".*l.*g.*"></property></bean><!-- 代理对象 -->//ProxyFactoryBean是⼀个代理,我们可以把它转换为//proxyInterfaces中指定的实现该interface的代理对象<bean id="serviceProxy"class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="Human"></property><property name="interceptorNames" value="BeforAdvisor"></property></bean>代理类publicclassStuTest {publicstaticvoidmain(String[] args){//通过ClassPathXmlApplicationContext实例化Spring的上下⽂ApplicationContext context=newClassPathXmlApplicationContext("applicationContext.xml");//通过ApplicationContext的getBean()⽅法,根据id来获取Bean的实例Sleepable s=(Sleepable)context.getBean("Human");s.sleep();}}。
SpringBoot通过自定义注解实现AOP切面编程实例
![SpringBoot通过自定义注解实现AOP切面编程实例](https://img.taocdn.com/s3/m/4d376f3ca22d7375a417866fb84ae45c3b35c270.png)
SpringBoot通过⾃定义注解实现AOP切⾯编程实例⼀直⼼⼼念的想写⼀篇关于AOP切⾯实例的博⽂,拖更了许久之后,今天终于着⼿下笔将其完成。
基础概念1、切⾯(Aspect)⾸先要理解‘切’字,需要把对象想象成⼀个⽴⽅体,传统的⾯向对象变成思维,类定义完成之后(封装)。
每次实例化⼀个对象,对类定义中的成员变量赋值,就相当于对这个⽴⽅体进⾏了⼀个定义,定义完成之后,那个对象就在那⾥,不卑不亢,不悲不喜,等着被使⽤,等着被回收。
⾯向切⾯编程则是指,对于⼀个我们已经封装好的类,我们可以在编译期间或在运⾏期间,对其进⾏切割,把⽴⽅体切开,在原有的⽅法⾥⾯添加(织⼊)⼀些新的代码,对原有的⽅法代码进⾏⼀次增强处理。
⽽那些增强部分的代码,就被称之为切⾯,如下⾯代码实例中的通⽤⽇志处理代码,常见的还有事务处理、权限认证等等。
2、切⼊点(PointCut)要对哪些类中的哪些⽅法进⾏增强,进⾏切割,指的是被增强的⽅法。
即要切哪些东西。
3、连接点(JoinPoint)我们知道了要切哪些⽅法后,剩下的就是什么时候切,在原⽅法的哪⼀个执⾏阶段加⼊增加代码,这个就是连接点。
如⽅法调⽤前,⽅法调⽤后,发⽣异常时等等。
4、通知(Advice)通知被织⼊⽅法,改如何被增强。
定义切⾯的具体实现。
那么这⾥⾯就涉及到⼀个问题,空间(切哪⾥)和时间(什么时候切,在何时加⼊增加代码),空间我们已经知道了就是切⼊点中定义的⽅法,⽽什么时候切,则是连接点的概念,如下⾯实例中,通⽤⽇志处理(切⾯),@Pointcut规则中指明的⽅法即为切⼊点,@Before、@After是连接点,⽽下⾯的代码就是对应通知。
@Before("cutMethod()")public void begin() {System.out.println("==@Before== lingyejun blog logger : begin");}5、⽬标对象(Target Object)被⼀个或多个切⾯所通知的对象,即为⽬标对象。
SpringAOP实现方式三之自动扫描注入【附源码】
![SpringAOP实现方式三之自动扫描注入【附源码】](https://img.taocdn.com/s3/m/e1c83c38bc64783e0912a21614791711cc79792a.png)
SpringAOP实现⽅式三之⾃动扫描注⼊【附源码】注解AOP实现这⾥唯⼀不同的就是application ⾥⾯不需要配置每个bean都需要配置了,直接⾃动扫描注册,主要知识点是怎么通过配置⽂件得到bean,注意类前⾯的@注解。
源码结构:1、⾸先我们新建⼀个接⼝,love 谈恋爱接⼝。
package com.spring.aop;/*** 谈恋爱接⼝** @author Administrator**/public interface Love{/** 谈恋爱⽅法*/void fallInLove();void test() throws Exception;}2、我们写⼀个Person类实现Love接⼝类声明前⾯加上了@Component 不加这个我们⽆法通过载⼊xml配置⽂件找到。
package com.spring.aop;import ponent;/*** ⼈对象** @author luwenbin006@**/@Componentpublic class Person implements Love{/** 重写谈恋爱⽅法*/@Overridepublic void fallInLove(){System.out.println("谈恋爱了...");}@Overridepublic void test() throws Exception{// TODO Auto-generated method stubthrow new Exception("我就说你们在⼀起不会幸福的,你能拿我怎么滴?");}}3、下⾯我们来写aop 注解通知类和前⾯有点不同哦 @Aspect前⾯加上了@Service【执⾏⽅法前执⾏⽅法后执⾏⽅法前后也称为环绕⽅法⽅法执⾏过程中抛出异常】package com.spring.aop;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.After;import ng.annotation.AfterThrowing;import ng.annotation.Around;import ng.annotation.Aspect;import ng.annotation.Before;import ng.annotation.Pointcut;import org.springframework.stereotype.Service;/*** 注解⽅式 aop通知类** @author luwenbin006@**/@Service@Aspectpublic class LoveHelper{@Pointcut("execution(* com.spring.aop.*..*(..))")private void loveMethod(){}// 定义⼀个切⼊点// 在调⽤⽅法之前执⾏执⾏拦截包com.spring.aop.*下所有的⽅法@Before("execution(* com.spring.aop.*..*(..))")public void before(JoinPoint point) throws Throwable{System.out.println("before::method "+ point.getTarget().getClass().getName() + "."+ point.getSignature().getName());System.out.println("谈恋爱之前必须要彼此了解!");}// 在调⽤⽅法前后执⾏@Around("execution(* com.spring.aop.*..*(..))")public Object around(ProceedingJoinPoint point) throws Throwable{System.out.println("around::method "+ point.getTarget().getClass().getName() + "."+ point.getSignature().getName());if (point.getArgs().length > 0){return point.proceed(point.getArgs());}else{return point.proceed();}}// 在调⽤⽅法之后执⾏@After("execution(* com.spring.aop.*..*(..))")public void afterReturning(JoinPoint point) throws Throwable{System.out.println("method " + point.getTarget().getClass().getName()+ "." + point.getSignature().getName());System.out.println("我们已经谈了5年了,最终还是分⼿了!");// System.out.println("我们已经谈了5年了,最终步⼊了结婚的殿堂!");}// 当抛出异常时被调⽤@AfterThrowing(value = "execution(* com.spring.aop.*..*(..))", throwing = "ex")public void doThrowing(JoinPoint point, Throwable ex){System.out.println("doThrowing::method "+ point.getTarget().getClass().getName() + "."+ point.getSignature().getName() + " throw exception");System.out.println(ex.getMessage());}}4、配置好application.xml 就配置好bean和aop通知类加上⼀句启⽤注解模式配置和⾃动扫描配置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一个非常有趣的使用spring框架AOP例子接触spring有一段时间了,不过都是看的多,写的少,工作忙,公司也不准备用。
自己写过一些小东西用到,也只用到了BeanFactory组装对象,JdbcTemplate代替jdbc,事务管理。
东抓一把,西抓一把,没形成系统。
最近也在看spring自带的reference,一时手痒,写了个AOP的创建advice的例子,比之单纯地使用TransationProxyFactoryBean 对AOP的理解又深入了点,打算看看它的源代码,基于CGLIB的实现对类的代理不了解,倒是好奇它如何实现对接口的代理??也就是利用J2SE的动态代理技术。
例子如下:讲述一间书店开始打折促销,规则是每一名顾客只能买一本书,而且已经脱销了。
你可以去掉TestAdvice里的注释看看各种运行结果,具体就不解释咯,在代码注释里。
首先,你必须对增强(advice)有所了解,增强就是在特定连接点执行的动作。
advice contains the logic of your aspect。
增强,分为4类:前增强(before)在连接点之前调用后增强(after)在连接点执行之后调用、环绕增强(around)完整控制整个方法流程,必须调用MethodInvocation的proceed促使真实操作发生异常增强针对某个异常抛出时调用书店,一个buyBook业务:package com.denny_blue.springdemo.aop;public interface BuyBook {public void buyBook(String customer,String book)throws NoThisBookException;}实现此接口的一个业务对象,如果顾客要买就抛出NoThisBookException异常。
package com.denny_blue.springdemo.aop;public class MyBuyBook implements BuyBook {public void buyBook(String customer,String book)throws NoThisBookException{if(book.equals(""))throw new NoThisBookException("对不起,没有"+book+"存货了!");System.out.println(customer+",你好,你已经购买了一本"+book+"!");}}自定义两个异常类,其中NoThisBookException被抛出时将触发MyThrowsAdvice调用://NoThisBookException.javapackage com.denny_blue.springdemo.aop;public class NoThisBookException extends RuntimeException {public NoThisBookException(String msg){super(msg);}}//BuyBookException.javapackage com.denny_blue.springdemo.aop;public class BuyBookException extends RuntimeException {public BuyBookException(String msg){super(msg);System.out.println(msg);}}OK,接下来就是各类增强了,前增强,在业务方法buyBook之前调用,显示欢迎信息:package com.denny_blue.springdemo.aop;import ng.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class MyBeforeAdvice implements MethodBeforeAdvice {public void before(Method arg0, Object[] arg1, Object target)throws Throwable {String customer=(String)arg1[0]; //第2个参数组就是被增强的方法传入的参数,本例中即customer,bookSystem.out.println("欢迎光临!"+customer+"!"); //显示欢迎信息!,在buyBook方法前调用}}然后是后增强,当顾客已经买了书之后,显示欢送信息:package com.denny_blue.springdemo.aop;import ng.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class MyAfterAdvice implements AfterReturningAdvice {public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {String customer=(String)arg2[0]; //同前增强一样,参数组3为传入参数,具体见spring docSystem.out.println("欢迎下次再来!"+customer+"!"); //显示欢送信息!}} 来源:考试大-Java认证OK,有了上面两个advice我们就能提供给顾客很好的服务态度了,等等?我们还有规则没实现,不是说一名顾客只能买一本书吗?OK,我们用环绕增强来解决,在环绕增强中保存一个HashSet,判断顾客是否来过,来过就抛出一个异常,没来过再放入此Set中:package com.denny_blue.springdemo.aop;import java.util.HashSet;import java.util.Set;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class MyAroundAdvice implements MethodInterceptor {private Set customers=new HashSet(); //保存购过书的顾客信息public Object invoke(MethodInvocation invocation) throws Throwable {String customer=(String)invocation.getArguments()[0];if(customers.contains(customer)){throw new BuyBookException("对不起,一名顾客只能买一本打折书!");}Object result=invocation.proceed(); //调用MyBuyBook中的buyBook方法,即真实操作customers.add(customer);return result;}}好了,最后一个,异常增强,当顾客要买时,我们的书店没书了,请仓库部门赶快订货!!package com.denny_blue.springdemo.aop;import org.springframework.aop.ThrowsAdvice;public class MyThrowsAdvice implements ThrowsAdvice {public void afterThrowing(NoThisBookException e){ //可以定义多个方法,只要传入的参数是不同异常System.out.print("通知仓库,赶紧加订书!");}}好了没?还没,我们需要一个XML文件来组装这些对象,来代理业务接口,完整的beans.xml如下,各元素的含义请自己查看spring reference?xml version="1.0" encoding="UTF-8"?>com.denny_blue.springdemo.aop.BuyBookmyBeforeAdvicemyAfterAdvicemyAroundAdvicemyThrowsAdvice我们先声明所有的bean,通过确定将要被增强的目标对象(target),我们可以很容易地替换这个目标对象,只要它实现业务接口。
代理的接口通过:com.denny_blue.springdemo.aop.BuyBook设定,然后是要用到一系列增强,注意,顺序是很有影响的!你可以尝试着改变顺序看看结果:)myBeforeAdvicemyAfterAdvicemyAroundAdvicemyThrowsAdvice一切准备好了,我们来测试吧,GO GO GOpackage test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext; import com.denny_blue.springdemo.aop.BuyBook;public class TestAdvice {public static void main(String args[]){ApplicationContext ctx=new FileSystemXmlApplicationContext("/src/beans.xml");//我的beans.xml放在项目下的src目录,eclipse环境下,请自己调整BuyBook buybook=(BuyBook)ctx.getBean("buyBook");buybook.buyBook("jordan","<深入浅出hibernate>");// buybook.buyBook("dennis",""); //去掉注释即可观察异常增强// buybook.buyBook("jordan","<深入浅出hibernate>"); //去掉注释即可观察环绕增强}}。