springAOP基于注解的使用方法和实现原理
springAOP即面向切面编程,可以在方法执行过程中动态的织入增强逻辑,其使用步骤为:
1. 导入aop模块的jar包,或在maven中添加依赖:spring-aspects
2. 定义目标类和目标方法,即需要增强的类和方法
3. 定义切面类和通知方法
4. 指定通知方法何时何地织入,即在切面类中添加切点和切面注解
5. 将目标类和切面类注册到同一个springIOC容器中
6. 告诉容器哪个是目标类、哪个是切面类,即在切面类上添加@Aspect注解
7. 如果容器中存在多个切面类且需要排序,可以让切面类实现Ordered接口
8. 开启基于注解的切面功能,即在切面类上添加@EnableAspectJAutoProxy注解
目标类
/**
* springAOP中的目标类
*/
public class MathTool { /**
* 执行除法逻辑
* @param i 被除数
* @param j 除数
* @return 商
*/
public double divide(int i, int j) {
System.out.println("--------目标方法开始执行--------");
double result = i / j;
return result;
}
}
切面类
/**
* 打印日志的切面类
*/
@Aspect
@EnableAspectJAutoProxy
public class LogAspect implements Ordered { //定义切点,即需要增强的方法
@Pointcut(value = "execution(public double cn.monolog.entity.MathTool.*(..))")
public void getPointcut() {} /**
* 在目标方法之前执行的通知方法
* @param joinPoint 切点
*/
@Before(value = "getPointcut()")
public void startLog(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
System.out.println("方法" + joinPoint.getSignature() + "即将执行,参数列表:" + Arrays.asList(args));
} /**
* 在目标方法之后执行的通知方法
* @param joinPoint 切点
*/
@After(value = "getPointcut()")
public void endLog(JoinPoint joinPoint) {
System.out.println("方法" + joinPoint.getSignature() + "执行完毕");
} /**
* 目标方法正常返回时的通知方法
* @param joinPoint 切点
* @param result 目标方法的返回值,通过@AfterReturning定义
* 注:当通知方法存在多个参数时,JoinPoint必须放在第一位
*/
@AfterReturning(value = "getPointcut()", returning = "result")
public void returningLog(JoinPoint joinPoint, Object result) {
System.out.println("方法" + joinPoint.getSignature() + "返回值为:" + result);
} /**
* 目标方法发生异常时的通知方法
* @param joinPoint 切点
* @param exception 目标方法抛出的异常,通过@AfterThrowing定义
* 注:当通知方法存在多个参数时,JoinPoint必须放在第一位
*/
@AfterThrowing(value = "getPointcut()", throwing = "exception")
public void exceptionLog(JoinPoint joinPoint, Exception exception) {
System.out.println("方法" + joinPoint.getSignature() + "抛出异常,异常信息为:" + exception);
} //Ordered接口提供的排序方法,返回值为执行顺序,数字越小越靠前
@Override
public int getOrder() {
return 1;
}
}
容器配置类
/**
* 容器配置类
* 用于测试springAOP
* 需要注册目标类和切面类
*/
@Configuration
@Import({AopDefinitionRegistrar.class})
public class AopBeanConfig {
}
/**
* 用于向容器中导入需要的组件
*/
public class AopDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册目标类
BeanDefinition mathTool = new RootBeanDefinition(MathTool.class);
registry.registerBeanDefinition("mathTool", mathTool);
//注册切面类
BeanDefinition logAspect = new RootBeanDefinition(LogAspect.class);
registry.registerBeanDefinition("logAspect", logAspect);
}
}
springAOP的实现原理
1. @EnableAspectJAutoProxy开启注解功能,并在容器中注册一个组件——AnnotationAwareAspectJProxyCreator,这个组件实现了SmartInstantiationAwareBeanPostProcessor,是一个后置处理器;
2. 在创建springIOC容器时,有一个步骤是refresh即刷新容器,在这个方法中,有一步是registerBeanPostProcessors,这一步会初始化所有的后置处理器,就是在这时生成了AnnotationAwareAspectJProxyCreator组件;
3. refresh后面还有一步,finishBeanFactoryInitilization,即初始化剩下的单实例bean,这时会生成目标类组件和切面类组件;
4. AnnotationAwareAspectJProxyCreator会对目标类组件和切面类组件进行拦截,即在这些组件创建完成并初始化之后,调用postProcessAfterInitialization方法,判断目标类组件是否需要增强,如果需要,会将切面类的通知方法包装成增强器(Advisor),然后用cglib动态代理(如果目标类实现了接口,也可以使用jdk动态代理)给目标类对象创建一个代理对象,这个代理对象中就有上述增强器;
5. 经过2-4步,容器就创建完毕,接下来代理对象执行目标方法,首先获取目标方法的拦截器链(即MethodInterceptor,由增强器包装而来),利用拦截器的链式机制依次进入每一个拦截器进行增强;
6. 拦截器链的执行效果
目标方法成功:前置通知 → 目标方法 → 后置通知 → 返回通知;
目标方法抛出异常:前置通知 → 目标方法 → 后置通知 → 异常通知。
springAOP基于注解的使用方法和实现原理的更多相关文章
- Spring-AOP 基于注解的实现
一.AOP: 是对OOP编程方式的一种补充.翻译过来为“面向切面编程”. 可以理解为一个拦截器框架,但是这个拦截器会非常武断,如果它拦截一个类,那么它就会拦截这个类中的所有方法.如对一个目标列的代理, ...
- springMVC 基于注解的controller
概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spring 2.5 又为 Spring MVC 引入了注解驱动功能.现在你无须让 Controller 继承任何接口,无需在 ...
- SpringMVC 基于注解的Controller详解
本文出处 http://blog.csdn.net/lufeng20/article/details/7598801 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spri ...
- spring mvc 基于注解的使用总结
本文转自http://blog.csdn.net/lufeng20/article/details/7598801 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sprin ...
- 使用 Spring 2.5 基于注解驱动的 Spring MVC
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-mvc/ 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sp ...
- web项目学习之基于注解的Controller
1. 低版本Spring MVC 实现Controller 使用过低版本 Spring MVC 的读者都知道:当创建一个 Controller 时,我们需要直接或间接地实现 org.springfra ...
- 使用 Spring 2.5 基于注解驱动的 Spring MVC--转
概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spring 2.5 又为 Spring MVC 引入了注解驱动功能.现在你无须让 Controller 继承任何接口,无需在 ...
- SpringMVC 基于注解的Controller @RequestMapping @RequestParam..
概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spring 2.5 又为 Spring MVC 引入了注解驱动功能.现在你无须让 Controller 继承任何接口,无需在 ...
- [问题解决]基于注解配置dubbo遇到ConnectionLoss for /dubbo/xxx问题解决
今天升级spring版本的时候,同时升级dubbo的版本,采用的是dubbo的基于注解的配置方法,采用curator作为dubbo的客户端, curator版本为4.1.0,启动之后,发现一直报错 C ...
随机推荐
- [51Nod1623] 完美消除
link $solution:$ 首先我们可以发现一个结论,对于一个数 $x$ ,它的最低修改次数为它每位与前去中是否都比此位上的数大,有则答案 $-1$ .因为若有小数则没有办法将其答案贡献变低. ...
- MFC- 网络编程
一.MFC网络编程 a)CAsyncSocket用于异步非阻塞类,用UDP通信: b)CAsyncSocket的子类(派生类):Csocket同步阻塞类,用于TCP通信: c)通信前,必须调用AfxS ...
- Spring Boot 支持https
1. 生成key JDK下 keytool -genkeypair -alias mySSL -keyalg RSA -keystore E:\tomcat.key 其中-alias是证书的别名,RS ...
- 基于Kintex Ultrasacle的万兆网络光纤 PCIe加速卡416 光纤PCIe卡
基于Kintex Ultrasacle的万兆网络光纤 PCIe加速卡 一.产品概述 本卡为企业级别板卡,可用于数据中心,安全领域数据采集处理.标准PCI Express全高板,适用于普通服务器.工作站 ...
- vue的v-for循环渲染列表时,解决没有:key警告问题(:key的作用)
:key是为vue的响应式渲染提供方法,在列表中单条数据改变的情况下,可以进行单独渲染,减少页面资源消耗. 当前页面如果有列表渲染v-for,并且在v-for的循环标签中没有:key元素时,控制台会出 ...
- maven 依赖显示红线 pom文件不显示红线的一种可能问题
pom文件引用的是CDH的jar包 而没有配置CDH的仓库 导致maven找不到资源 ,依赖显示红色波浪,并且在仓库内生成了一堆.lastupdate文件 解决: 1. 删除本地仓库内所有的.las ...
- php.ini中时区设置不成功解决方法
一.在php.ini的[Date]中加入 [Date] date_default_timezone_set('UTC'); date.timezone = "Asia/Shanghai&qu ...
- 负载均衡(二)DNS负载均衡
一.DNS原理及解析过程详解 相信大家在平时工作中都离不开DNS解析,DNS解析是互联网访问的第一步,无论是使用笔记本浏览器访问网络还是打开手机APP的时候,访问网络资源的第一步必然要经过DNS解析流 ...
- Facebook再现丑闻,约100位应用程序开发人员偷看用户数据
Facebook今天披露了另一起安全事件,承认大约100名应用程序开发人员可能不正确地访问了某些Facebook组中的用户数据,包括他们的姓名和个人资料图片. 在周二发布的博客文章中,Facebook ...
- 利用雅虎ycsb对cassandra做性能测试
准备: 环境: 两台虚拟机:ip:192.168.138.128/129;配置:2核4G: 版本:apache-cassandra-3.10 ycsb-cassandra-binding-0.1 ...