Aop相关BeanDefinition注册

org.springframework.aop.config.ConfigBeanDefinitionParser
注册AspectJAwareAdvisorAutoProxyCreator 的 BeanDefinition
image.png
image.png
parseAspect()解析出Aspect代理的BeanDefinition。
image.png

AbstractAutoProxyCreator

postProcessBeforeInstantiation

image.png

shouldSkip()

AspectJAwareAdvisorAutoProxyCreator#shouldSkip()

image.png
从容器中找到Advisor添加:
image.png
创建Advisor过程会存放一个cache:
image.png
创建Advisor过程:

image.png
image.png

getEarlyBeanReference

image.png

——-

AOP原理

  1. @EnableAspectJAutoProxy 中有 @Import(AspectJAutoProxyRegistrar.class)
  2. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
  3. ImportBeanDefinitionRegistrar 注入AnnotationAwareAspectJAutoProxyCreator

手动的话通过ProxyFactoryBean手动注册代理,麻烦,AutoProxyCreator自动注入
aop - 图11
aop - 图12

AbstractAutoProxyCreator 实现了 SmartInstantiationAwareBeanPostProcessor

AbstractAutoProxyCreator中的postProcessBeforeInstantiation()和postProcessAfterInitializatio()

  • postProcessBeforeInstantiation中如果获取到自定义的TargetSource则直接创建代理对象,创建代理对象之前先调用getAdvicesAndAdvisorsForBean获取拦截对象Advisors,然后调用createProxy创建代理对象。
  • 如果没有自定义TargetSource,则走到postProcessAfterInitialization方法创建代理,逻辑跟上面一样,唯一不同的是创建了个默认的TargetSource (SingletonTargetSource)

在对象实例化前(postProcessBeforeInstantiation)的扩展中,主要对配置了customTargetSourceCreators属性的情况进行处理,而默认的处理都是在初始化后(postProcessAfterInitialization)扩展里执行的。
Spring源码阅读-AOP实现核心类AbstractAutoProxyCreator - 程小员的个人页面 - OSCHINA

TargetSource

  1. // 首先定义一个被代理的目标类
  2. public class TargetBean {
  3. // 此方法演示使用
  4. public void show() {
  5. System.out.println("show");
  6. }
  7. }
  8. // 接下来是创建代理对象的过程
  9. public class AOPDemo {
  10. public static void main(String[] args) {
  11. TargetBean target = new TargetBean();
  12. TargetSource targetSource = new SingletonTargetSource(target);
  13. // 使用SpringAOP框架的代理工厂直接创建代理对象
  14. TargetBean proxy = (TargetBean) ProxyFactory.getProxy(targetSource);
  15. // 这里会在控制台打印:com.lixin.aopdemo.TargetBean$$EnhancerBySpringCGLIB$$767606b3
  16. System.out.println(proxy.getClass().getName());
  17. }
  18. }

实现自定义的TargetSource

  1. public class Apple {
  2. private int id;
  3. public Apple(int id) {
  4. this.id = id;
  5. }
  6. public void eat() {
  7. System.out.println("eat apple, id: " + id);
  8. }
  9. }
  1. public class AppleTargetSource implements TargetSource {
  2. private Apple apple1;
  3. private Apple apple2;
  4. public AppleTargetSource() {
  5. this.apple1 = new Apple(1);
  6. this.apple2 = new Apple(2);
  7. }
  8. @Override
  9. public Class < ?>getTargetClass() {
  10. return Apple.class;
  11. }
  12. @Override
  13. public boolean isStatic() {
  14. return false;
  15. }
  16. @Override
  17. public Object getTarget() throws Exception {
  18. ThreadLocalRandom random = ThreadLocalRandom.current();
  19. int index = random.nextInt(2);
  20. return index % 2 == 0 ? apple1: apple2;
  21. }
  22. @Override
  23. public void releaseTarget(Object target) throws Exception {}
  24. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
  4. 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.xsd">
  5. <bean id="targetSource" class="chapter7.eg10.AppleTargetSource"/>
  6. <aop:aspectj-autoproxy/>
  7. </beans>
  1. public class CustomTargetSourceApp {
  2. public static void main(String[] args) throws Exception {
  3. ApplicationContext context = new ClassPathXmlApplicationContext("chapter7/eg10/applicationContext.xml");
  4. TargetSource targetSource = (TargetSource) context.getBean("targetSource");
  5. for (int i = 0; i < 10; i++) {
  6. Apple apple = (Apple) targetSource.getTarget();
  7. apple.eat();
  8. }
  9. }
  10. }

Spring Aop之Target Source详解_java_lw_yang的博客-CSDN博客
官方文档:
aop - 图13
一般自定义target source都是 prototype的
37. Classic Spring AOP Usage

@Aspect在哪被找到的?

AbstractAutoProxyCreator#postProcessBeforeInstantiation 虽然大部分代理都不是这里创建的,但这里 shouldSkip(beanClass, beanName) 【比较隐蔽】会记录有@Aspect注解名字的bean
aop - 图14
AnnotationAwareAspectJAutoProxyCreator会持有BeanFactoryAspectJAdvisorsBuilder
aop - 图15

  1. // 这个很重要,在Bean实例化之前,先给一个机会,看看缓存里有木有,有就直接返回得了
  2. // 简单的说:其主要目的在于如果用户使用了自定义的TargetSource对象,则直接使用该对象生成目标对象,而不会使用Spring的默认逻辑生成目标对象
  3. // (并且这里会判断各个切面逻辑是否可以应用到当前bean上)
  4. @Override
  5. public Object postProcessBeforeInstantiation(Class < ?>beanClass, String beanName) throws BeansException {
  6. Object cacheKey = getCacheKey(beanClass, beanName);
  7. // beanName无效或者targetSourcedBeans里不包含此Bean
  8. if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
  9. //advisedBeans:已经被通知了的(被代理了的)Bean~~~~ 如果在这里面 也返回null
  10. if (this.advisedBeans.containsKey(cacheKey)) {
  11. return null;
  12. }
  13. // isInfrastructureClass:Advice、Pointcut、Advisor、AopInfrastructureBean的子类,表示是框架所属的Bean
  14. // shouldSkip:默认都是返回false的。AspectJAwareAdvisorAutoProxyCreator重写此方法:只要存在一个Advisor ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)成立 就返回true
  15. if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
  16. // 所以这里会把我们所有的Advice、Pointcut、Advisor、AopInfrastructureBean等Bean都装进来
  17. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  18. return null;
  19. }
  20. }
  21. //到这,只有在TargetSource中没有进行缓存,并且应该被切面逻辑环绕,但是目前还未生成代理对象的bean才会通过此方法
  22. // Create proxy here if we have a custom TargetSource.
  23. // 如果我们有TargetSourceCreator,这里就会创建一个代理对象
  24. // getCustomTargetSource逻辑:存在TargetSourceCreator 并且 beanFactory.containsBean(beanName) 然后遍历所有的TargetSourceCreator,调用getTargetSource谁先创建不为null就终止
  25. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  26. // 若创建好了这个代理对象,继续进一步的操作:::
  27. if (targetSource != null) {
  28. if (StringUtils.hasLength(beanName)) {
  29. // 缓存起来
  30. this.targetSourcedBeans.add(beanName);
  31. }
  32. //getAdvicesAndAdvisorsForBean:方法判断当前bean是否需要进行代理,若需要则返回满足条件的Advice或者Advisor集合
  33. // 这个方法由子类实现,AbstractAdvisorAutoProxyCreator和BeanNameAutoProxyCreator 代表中两种不同的代理方式
  34. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  35. // 顾名思义,就是根据目标对象创建代理对象的核心逻辑了 下面详解
  36. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  37. // 把创建好的代理 缓存~~~
  38. this.proxyTypes.put(cacheKey, proxy.getClass());
  39. return proxy;
  40. }
  41. return null;
  42. }
  • 【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)_YourBatman-CSDN博客

    AOP代理对象如何被创建的

    JdkDynamicAopProxy

    // 真正创建JDK动态代理实例的地方 @Override public Object getProxy(@Nullable ClassLoader classLoader) {

    1. if (logger.isDebugEnabled()) {

    logger.debug(“Creating JDK dynamic proxy: target source is “ + this.advised.getTargetSource());

    1. }
    2. // 这部很重要,就是去找接口 我们看到最终代理的接口就是这里返回的所有接口们(除了我们自己的接口,还有Spring默认的一些接口) 大致过程如下:
    3. //1、获取目标对象自己实现的接口们(最终肯定都会被代理的)
    4. //2、是否添加`SpringProxy`这个接口:目标对象实现对就不添加了,没实现过就添加true
    5. //3、是否新增`Adviced`接口,注意不是Advice通知接口。 实现过就不实现了,没实现过并且advised.isOpaque()=false就添加(默认是会添加的)
    6. //4、是否新增DecoratingProxy接口。传入的参数decoratingProxy为true,并且没实现过就添加(显然这里,首次进来是会添加的)
    7. //5、代理类的接口一共是目标对象的接口+上面三个接口SpringProxy、Advised、DecoratingProxy(SpringProxy是个标记接口而已,其余的接口都有对应的方法的)
    8. //DecoratingProxy 这个接口Spring4.3后才提供
    9. Class < ?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    10. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    11. // 第三个参数传的this,处理器就是自己嘛 到此一个代理对象就此new出来啦
    12. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

    }

  • 【小家Spring】详解Spring AOP的底层代理JdkDynamicAopProxy和ObjenesisCglibAopProxy的源码分析(介绍CGLIB使用中的坑)_java_BAT的乌托邦-CSDN博客

    CglibAopProxyObjenesisCglibAopProxy

    aop - 图16

@within和@target的区别

Spring—@within和@target的区别_demon7552003的小本本-CSDN博客

AopContext.currentProxy()

使用AopContext.currentProxy() 需要@EnableAspectJAutoProxy(exposeProxy = true)
image.png

AOP执行顺序

多个Aspect情况

@Order 越小优先级也高

同一个Aspect,不同类型增强

aop - 图18

同一个Aspect,同种类型的增强

按方法名排序

  • 方法名长度短的优先
  • 长度相同按ASCII码,ASCII小的优先。