spring aop advice注解实现的几种方式
来源:互联网 发布:在新加坡怎么用淘宝 编辑:程序博客网 时间:2024/05/20 11:52
spring的aop advice(可以理解为切面上的逻辑)用注解来实现有五种实现方式:
- @Before(execution) 在方法执行前拦
- @AfterReturning(execution)在方法正常return结束后拦截
- @AfterThrowing(execution) 在方法抛出异常时拦截
- @After(execution) 在方法结束后拦截,无论正常结束还是异常结束
- @Around(execution)唯一可以使用ProceedingJoinPoint参数来控制流程的advice,在方法执行前拦截,可以在切面逻辑中手动释放拦截,且可以在其后加入逻辑代码,该代码段会在方法执行后执行.
这几种方式如果同时存在 , 会有一个先后顺序,下边测试后可以从打印结果中很明显地看到,但是一般情况下,尽量避免用这种先后顺序的方式来决定切面逻辑的设计,如果切面逻辑很复杂,可以用@Around整合在一起.
注意 : “表达式(execution)” 匹配到的方法必须为interface的实现类才可以,否则会抛出以下异常:Cannot proxy target class because CGLIB2 is not available.
如果一个类实现了接口 , spring就会通过jdk自带的Proxy 和 InvocationHandler自动生成代理 , 如果没有实现接口, 需要依赖cglib包 , 以直接操作二进制码的方式 , 来生成代理代码.
可以将获取到对象的class打印出来,可以很明显看到其中有”$$EnhancerByCGLIB”的字样,它是一个代理对象.
另外 , 测试中出现一个问题 , PointCut() 无法正常调用, 后来发现是aspectjrt 版本的问题 ,因为是跟着马士兵老师的视频走的 , 所以用的spring 2.5.6 的版本 , 我用pom构建项目的, spring2.5.6中集成的aspectjrt是1.6.1 版本的 , 这个版本和jdk1.7有冲突 , 将版本更换为新版的1.8.7就好了
下边上代码:
切面类:
@Aspect@Componentpublic class LogInterceptor { //advice 切点语法规则,方法体不执行,其他advice可以直接将该方法作为参数 //按照该语法来执行拦截 @Pointcut("execution(* com.pindao.nine.dao.UserDao.show* (..))") public void pointCut1(){ System.out.println("this is pointCut"); } //拦截在方法执行之前 @Before("pointCut1()") public void before(){ System.out.println("method start..."); } //拦截在方法体执行之后,无论正常执行结束或异常结束 @After("execution(* com.pindao.nine.dao.UserDao.show* (..))") public void after(){ System.out.println("method end!"); } //拦截在方法正常return之后 @AfterReturning(value = "pointCut1()") public void afterReturn(){ System.out.println("this is afterReturing pointcut!"); } //拦截在方法抛出异常之后 @AfterThrowing("pointCut1()") public void afterThrowing(){ System.out.println("this is afterThrowing pointcut!"); } //拦截在方法体执行之前,插入代码,需要手动释放拦截,并且可以在继续运行之后插入代码 //ProceedingJoinPoint 参数只能在@Around下用,在其他advice下用,会抛出异常 @Around("pointCut1()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("this is around pointcut start..!"); //拦截结束,程序继续运行, 继续下一个拦截或者进行正常逻辑代码 Object obj = pjp.proceed(); System.out.println("this is around pointcut end..!"); return obj; }}
执行切面的bean():
@Component("userDao")public class UserDaoImpl implements UserDao { public void showUser() { System.out.println("this is the real method start...");// int i = 1/0; System.out.println("this is the real method end"); return 0; }}
spring启用注解和切面配置 beans.xml:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <context:component-scan base-package="com.pindao.nine" /><!--aspectj是一个面向切面的框架,spring的aop,是基于aspectj来实现的--> <aop:aspectj-autoproxy /></beans>
手动启动spring容器,调用showUser()方法:
@Testpublic void testShowUserDao() throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserDao userDao = (UserDao) context.getBean("userDao"); int result = userDao.showUser(); System.out.println(result);}
执行结果:
1. 正常流程:
method start...this is around pointcut start..!this is the real method start...this is the real method endmethod end!this is afterReturing pointcut!this is around pointcut end..!0
2.方法体抛出异常流程:
method start...this is around pointcut start..!this is the real method start...method end!this is afterThrowing pointcut!java.lang.ArithmeticException: / by zero ......
下边是maven依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>2.5.6</version> <exclusions> <exclusion> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </exclusion> <exclusion> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>2.5.6</version> <exclusions> <exclusion> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </exclusion> <exclusion> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version></dependency><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.7</version></dependency><!-- cglib通过二进制的方式生成代理类 --><dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.0</version></dependency>
- spring aop advice注解实现的几种方式
- Spring AOP的几种实现方式
- Spring AOP的几种实现方式
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- Spring使用注解的方式实现AOP
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- 应用Spring的注解方式实现AOP
- 注解方式实现Spring的aop
- 应用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- 使用Spring的注解方式实现AOP
- Spring 注解方式实现的AOP
- 使用Spring的注解方式实现AOP
- Android 弹出框LemonBubble提示控件
- ReentrantLock 源码分析
- Webx框架指南(转载)
- php7下安装event扩展
- LBS定位和GPS定位的区别
- spring aop advice注解实现的几种方式
- mysql的锁机制
- C++基础
- 神经网络基础
- MySQL 乐观锁与悲观锁
- Android Universal Image Loader 源码分析
- Redis发布、订阅
- Android从0到完整项目(1) 创建工程
- java八种基本数据类型