Spring之AOP基础知识
Posted 敲代码的小小酥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring之AOP基础知识相关的知识,希望对你有一定的参考价值。
1.基本概念
切面(Aspect)带有advisor英文的都是切面:要增强的功能,都是切面,比如日志,事务,缓存等功能。
代理:内存中动态形成的对象
增强:具体的增强代码
切点: 连接点的集合
连接点:一个连接点对应一个被代理方法
2.切面Advisor的两个重要元素:切点pointcut和增强Advice
Pointcut来判断哪些类需要生成代理对象,进行增强。Adivce就是要增强的方法。
PonitCut中,通过ClassFilter拦截要代理的类,通过MethodMatcher拦截要增强的方法。
拦截方法是针对@Transactional等注解的方法。
3.Spring AOP的入口是AbstractAutoProxyCreator类的postProcessAfterInitialization方法,该类是个BeanPostProcessor类,在对象实例化完成后,有一个埋点,调用了这个方法,进行AOP,生成代理对象。
4.增强的注解总结 @Before @Around等。一个注解,会形成一个advisor切面类。@Aspect里写多个这种注解,就会生成多个advisor切面类。
6.MethodInvocation m=ExposeInvocationInterceptor.currentInvocation();
在增加方法里调用,可以获得当前参数?解决参数传递问题? 研究这个方法以及默认切面的生成。
AOP中三个工具类要知道:
ProxyFactory: 根据接口,接口类加载器等参数,获取到代理对象
AopUtils: 将当前代理对象放在了ThreadLocal中,如果使用了AOP,可以通过currentProxy方法获取当前的代理对象。
ExposeInvocationInterceptor:默认生成的拦截器链,排在拦截器的第一位。是将MethodInteceptor对象本身放在了ThreadLocal中,可以在当前线程中获得。
9.JDK动态代理是面向接口的,CGLIB是面像对象的。如果一个类没有接口,还用jdk动态代理,那spring会自动转成cglib。
11.ProxyFactory存放了切面等等元素,研究这个类,看是否能掌握AOP的实现原理。一个代理对象,对应着一个ProxyFactory和JdkDynamicAopproxy对象。而不是整个工程里只有一个ProxyFactory对象。
ProxyFactory里存着advisors切面类,targetSource被代理实例
12.代理对象在启动的过程就生成了。最终代理对象存储在一级缓存中
13.@Transactional注解的方法,代理原理研究。只要有@Transactional的方法,那么这个类就会生成代理类。而对于那些没有增强的方法,直接走反射调用,调用target对象的原生方法。对于需要加强的类,走advice增强代码。
如果同一个类里一个普通方法调用@Transactonal方法,直接调用,那么不会走代理的增强方法,而是走这个真实方法,这样就起不到增强的作用了。需要从applicationcontext.getBean中获取对象本身,这样拿到的是代理对象。然后用代理对象,调用@Transactional的方法,这样会走加强。
或者调用AopContext.currentProxy()获得当前对象的代理对象。
研究AopContext类的用法。
14.当用代理对象调用方法的时候,spring会遍历这个对象的所有切面,然后判断调用的方法是否是加强方法,如果是加强方法,则调用增强方法,如果不是,则调用原生方法。可见,spring也是通过循环遍历,来判断哪个方法是增强的,哪个方法是原生的。
16.自定义的@Around方法里,也要声明proceed()方法吗。否则链式调用会中断吗? @Around中的proceed方法和连接点的proceed方法不是一个类的方法。@Around中的proceed方法就是调用目标方法。而连接点的proceed方法是链式调用拦截器的方法
17@Autowired进来的对象,都是单例的,那么@Autowired多例对象,该如何呢?启动过程中,就已经定了@Autowired的对象,不管是单例还是多例,依赖注入时getBean就获到一个对象,所以,即使是多例,也是只拿到同一个对象。
如果想拿到不同的对象,应该怎么做呢,需要在scope注解中用proxyMode属性的TARGET_CLASS,将其变成代理对象。获取代理对象的时候,会多次调用getBean,多例就返回多个对象了。(想清楚其中原理)
疑问:被代理的对象,有@Component注解,spring容器中还会有这个类吗?被代理的对象,可以不用@Component修饰吗?
被代理的对象,即使没有@Component注解,也能纳入Spring容器。只不过这个对象不能通过@Autowired获得,只能通过ApplicationContext.getBean方法获得。
18.被代理对象类的注解,和方法上的注解,获取方式都发生了变化:
获取方法上的注解: Method method=AopUitls.getNostSpecificMethod(method,targetClass);
获取类上的注解:AnnotatedElementUtils.findMergedAnnotation(handler.getClass(),CIMHandler.class);
因为代理是面向接口的,所以直接拿是不行的,需要通过代理对象获取原生对象,再拿注解
以上是关于Spring之AOP基础知识的主要内容,如果未能解决你的问题,请参考以下文章