Spring中的AOP详解

AOP

Spring的另一个核心是AOP,AOP全称Aspect-Oriented Programming译为面向切面编程。AOP可以说是对OOP(面向对象编程)的补充和完善,在程序原有的纵向执行流程中,针对某一个或某些方法添加通知,形成横切面的过程就叫做面向切面编程。简单来说,用于通过在方法执行前、执行后或抛出异常时动态地添加额外的功能就是面向切面编程。AOP 可以帮助解耦应用程序的横切关注点,如日志记录、事务管理、性能监控等,从而提高代码的模块性和复用性。

实现AOP的技术,主要分为两类,一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“切面”,从而使得编译器可以在编译期间织入有关“切面”的代码,属于静态代理。AOP的工作原理主要基于对程序执行过程中特定点的拦截和增强。动态代理刚好就可以实现这个功能,AOP用的就是动态代理。

使用AOP

使用AOP大致可以分为三步:

  1. 将业务逻辑组件和切面类都加入到容器中,并用Component@Aspect注解标注切面类。
    @Aspect
    @Component
    public class LoggingAspect {}
    
  2. 在切面类的通知方法上,要注意切面表达式的写法,标注通知注解,告诉Spring何时何地的运行:
    • @Before:前置通知,在目标方法运行之前执行;
    • @After:后置通知,在目标方法运行之后执行,无论方法是否出现异常都会执行;
    • @Around:环绕通知,通过joinPoint.proceed()方法手动控制目标方法的执行;
    • @AfterThrowing:异常通知,在目标方法出现异常之后执行;
    • @AfterReturning:返回通知,在目标方法返回之后执行;
    @Aspect
    @Component
    public class LoggingAspect {
    
        @Before("execution(* com.example.service.*.*(..))")
        public void logBefore() {
            System.out.println("Executing method in service layer...");
        }
    
        @After("execution(* com.example.service.*.*(..))")
        public void logAfter() {
            System.out.println("Method execution completed.");
        }
    
        @Around("execution(* com.example.service.*.*(..))")
        public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("Before method execution.");
            Object result = joinPoint.proceed();
            System.out.println("After method execution.");
            return result;
        }
    
        @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "error")
        public void logAfterThrowing(Throwable error) {
            System.out.println("Exception occurred: " + error);
        }
    
        @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
        public void logAfterReturning(Object result) {
            System.out.println("Method returned value: " + result);
        }
    }
    
  3. 使用@EnableAspectJAutoProxy开启基于注解的AOP模式。
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopApplication {
       public static void main(String[] args) {
          SpringApplication.run(SpringAopApplication.class, args);
       }
    }
    
execution表达式

execution表达式用于定义切入点,作用是什么时候触发切面。execution表达式语法:

execution(modifiers-pattern ret-type-pattern declaring-type-pattern name-pattern(param-pattern) throws-pattern)
  • modifiers-pattern(可选):方法修饰符模式,如publicprotected
  • ret-type-pattern:返回类型模式,可以是具体类型,如String,也可以是通配符(*表示任意返回类型)。
  • declaring-type-pattern(可选):声明类型模式,即方法所属的类或接口,可以是具体类名,如com.example.MyClass或通配符,如com.example.*
  • name-pattern:方法名模式,可以是具体方法名(如myMethod),也可以是通配符(如*表示任意方法名)。
  • param-pattern:参数模式,可以是具体参数类型,如(String, int),也可以是通配符,如(..)表示任意参数类型和数量。
  • throws-pattern(可选):异常模式,可以是具体异常类型,如throws IOException

execution表达式举例:

  • 匹配任意方法。
    @Before("execution(* *(..))")
    public void logBeforeAllMethods() {
        System.out.println("Executing any method...");
    }
    
  • 匹配特定类的所有方法。
    @Before("execution(* com.example.MyClass.*(..))")
    public void logBeforeMyClassMethods() {
        System.out.println("Executing method in MyClass...");
    }
    
  • 匹配特定包中的所有方法。
    @Before("execution(* com.example..*.*(..))")
    public void logBeforePackageMethods() {
        System.out.println("Executing method in com.example package...");
    }
    
  • 匹配特定返回类型的方法。
    @Before("execution(String *(..))")
    public void logBeforeStringMethods() {
        System.out.println("Executing method with String return type...");
    }
    
  • 匹配特定方法名。
    @Before("execution(* myMethod(..))")
    public void logBeforeMyMethod() {
        System.out.println("Executing myMethod...");
    }
    
  • 匹配特定参数类型的方法。
    @Before("execution(* *(String, int))")
    public void logBeforeStringIntMethods() {
        System.out.println("Executing method with String and int parameters...");
    }
    
  • 匹配没有参数的方法。
    @Before("execution(* *())")
    public void logBeforeNoArgMethods() {
        System.out.println("Executing no-arg method...");
    }
    
  • 匹配带有特定修饰符的方法。
    @Before("execution(public * *(..))")
    public void logBeforePublicMethods() {
        System.out.println("Executing public method...");
    }
    
切面执行顺序

在Spring AOP中,注意切面执行顺序非常重要,因为不同切面可能会对同一个方法执行不同的逻辑,这些逻辑的执行顺序可能会影响应用程序的行为和结果。

举一个例子,一个简单的银行转账操作,其中涉及日志记录、事务管理和安全检查三个切面。如果不考虑AOP的顺序,就是按照Spring加载顺序来,可能会导致事务管理在安全检查、日志记录的前面,这样可能会造成一些不安全的操作会被执行。但是我们期望的是先执行安全检查,再执行事务管理,最后再执行日志记录。

@Order(1)  // 优先级最高
public class SecurityAspect {
   @Before("execution(* com.example.service.BankService.transfer(..))")
   public void checkSecurity() {
      System.out.println("Security: Performing security check...");
   }
}

@Order(2)  // 优先级中等
public class TransactionAspect {
   @Before("execution(* com.example.service.BankService.transfer(..))")
   public void startTransaction() {
      System.out.println("Transaction: Starting transaction...");
   }
}

@Order(3)  // 优先级最低 
public class LoggingAspect {
   @Before("execution(* com.example.service.BankService.transfer(..))")
   public void logBefore() {
      System.out.println("Logging: Starting method execution...");
   }
}

AOP工作原理

要想AOP起作用,就要加@EnableAspectJAutoProxy注解,所以AOP的原理可以从该注解入手研究。它是一个复合注解,启动的时候,给容器中导入了一个AspectJAutoProxyRegistrar组件。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}

AspectJAutoProxyRegistrar该类实现了ImportBeanDefinitionRegistrar接口,而该接口的作用是给容器中注册Bean。所以AspectJAutoProxyRegistrar作用是添加自定义组件给容器中注册Bean。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        // 注册了 AnnotationAwareAspectJAutoProxyCreator 组件
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        // 获取 @EnableAspectJAutoProxy 中的属性,做一些工作
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

AspectJAutoProxyRegistrar组件何时注册?关键代码如下:

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

该方法是给容器中注册了一个AnnotationAwareAspectJAutoProxyCreator组件。

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        //注册或者升级AutoProxyCreator定义beanName为
        // org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        //对于proxy-target-class以及expose-proxy属性的处理
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        //注册组件并通知,便于监听器进一步处理,其中BeanDefinition的className
        // 为AnnotationAwareAspectJAutoProxyCreator
        registerComponentIfNecessary(beanDefinition, parserContext);
}

在这里插入图片描述

@EnableAspectJAutoProxy注解最主要的作用实际上就是通过@Import注解把AnnotationAwareAspectJAutoProxyCreator这个对象注入到Spring容器中。现在只要把AnnotationAwareAspectJAutoProxyCreator组件何时注册搞懂,AspectJAutoProxyRegistrar组件何时注册也就明白了。AnnotationAwareAspectJAutoProxyCreator继承关系:

AnnotationAwareAspectJAutoProxyCreator
    extends AspectJAwareAdvisorAutoProxyCreator
        extends AbstractAdvisorAutoProxyCreator
            extends AbstractAutoProxyCreator
                extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware
                    extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean 

其中的一个父类为AbstractAutoProxyCreator这个父类实现了SmartInstantiationAwareBeanPostProcessor接口,该接口是一个后置处理器接口,同样实现了BeanFactoryAware接口,这意味着,该类可以通过接口中的方法进行自动装配BeanFactorySmartInstantiationAwareBeanPostProcessorBeanFactoryAware这两个接口在AOP体系中具体的实现方法:

  1. AbstractAutoProxyCreator
    • 重写BeanFactoryAware接口中的setBeanFactory方法;
    • 重写SmartInstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiationpostProcessAfterInitialization方法;
  2. AbstractAdvisorAutoProxyCreator
    • 重写BeanFactoryAware接口中的setBeanFactory方法;
  3. AnnotationAwareAspectJAutoProxyCreator
    • 重写BeanFactoryAware接口中的initBeanFactory方法;

在重写BeanFactoryAware接口中的initBeanFactory方法,打断点即可看到类似下面的方法调用栈:

AnnotationConfigApplicationContext.AnnotationConfigApplicationContext()
    -->AbstractApplicationContext.refresh() //刷新容器,给容器初始化bean
        -->AbstractApplicationContext.finishBeanFactoryInitialization()
            -->DefaultListableBeanFactory.preInstantiateSingletons()
                -->AbstractBeanFactory.getBean()
                    -->AbstractBeanFactory.doGetBean()
                        -->DefaultSingletonBeanRegistry.getSingleton()
                            -->AbstractBeanFactory.createBean()
                                -->AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
                                    -->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
                                        -->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
                                            -->调用AOP相关的后置处理器

其中AbstractApplicationContext.refresh()方法,调用了registerBeanPostProcessors方法,它是用来注册后置处理,也是在这个方法中完成了对AnnotationAwareAspectJAutoProxyCreator的注册。注册完BeanPostProcessor后,还调用了finishBeanFactoryInitialization方法,完成BeanFactory初始化工作,并创建剩下的单实例Bean。

@Override
public void refresh() throws BeansException, IllegalStateException {
    // .....

    // Register bean processors that intercept bean creation.
    registerBeanPostProcessors(beanFactory);

    // .....

    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);

    // .....
}

下面详细的说明registerBeanPostProcessorsfinishBeanFactoryInitialization这两个方法。

registerBeanPostProcessors

registerBeanPostProcessors方法中注册了所有的BeanPostProcessor,注册顺序为:

  1. 注册实现了PriorityOrdered接口的BeanPostProcessor
  2. 注册实现了Ordered接口的BeanPostProcessor
  3. 注册常规的BeanPostProcessor,也就是没有实现优先级接口的BeanPostProcessor
  4. 最后才注册Spring内部BeanPostProcessor

由于AnnotationAwareAspectJAutoProxyCreator类间接实现了Ordered接口,所以它是在注册实现Ordered接口的BeanPostProcessor中完成注册。在注册时会调用AbstractBeanFactory.getBean() -> AbstractBeanFactory.doGetBean()方法创建Bean。doGetBean()方法作用为,创建Bean、给Bean中的属性赋值、初始化Bean。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    // 创建 Bean 实例
    Object beanInstance = createBeanInstance(mbd, beanName, args);
    // 提前暴露已经创建的 Bean 实例,用于解决循环依赖问题
    Object exposedObject = beanInstance;
    try {
        // 给 Bean 实例应用属性填充,包括依赖注入
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化 Bean,执行各种初始化方法
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }catch (Exception ex) {
        throw new BeanCreationException(beanName, "Initialization of bean failed", ex);
    }
    // 注册销毁回调,用于在 Bean 销毁时执行清理操作
    registerDisposableBeanIfNecessary(beanName, exposedObject, mbd);
    return exposedObject;
}

当初始化Bean时,initializeBean方法会调用BeanPostProcessorBeanFactory以及Aware接口的相关方法,这也是BeanPostProcessor初始化Bean的原理。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    // ...
    invokeAwareMethods(beanName, bean);   //处理Aware接口的方法回调

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行后置处理器的postProcessBeforeInitialization方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        // 执行自定义的初始化方法,也就是在这执行 setBeanFactory方法
        invokeInitMethods(beanName, wrappedBean, mbd);  
    }catch (Throwable ex){
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex);
    }
    // ...
    if (mbd == null || !mbd.isSynthetic()) {
        // 执行后置处理器的postProcessAfterInitialization方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

// ...invokeAwareMethods方法简要 ...
private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

initializeBean方法的作用为,invokeAwareMethods方法处理Aware接口的方法回调、执行后置处理器的postProcessBeforeInitialization方法、执行自定义的初始化方法invokeInitMethods、执行后置处理器的postProcessAfterInitialization方法。initializeBean方法执行成功,AnnotationAwareAspectJAutoProxyCreator组件才会注册和初始化成功。

finishBeanFactoryInitialization

除了弄懂AnnotationAwareAspectJAutoProxyCreator组件何时注册,也需要知道它什么时候被调用,这就涉及到finishBeanFactoryInitialization方法。

AnnotationConfigApplicationContext.AnnotationConfigApplicationContext()
    -->AbstractApplicationContext.refresh() // 刷新容器,给容器初始化bean
        -->AbstractApplicationContext.finishBeanFactoryInitialization() // 调用
            -->DefaultListableBeanFactory.preInstantiateSingletons()
                -->AbstractBeanFactory.getBean()
                    -->AbstractBeanFactory.doGetBean()
                        -->DefaultSingletonBeanRegistry.getSingleton()
                            -->AbstractBeanFactory.createBean()
                                -->AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
                                    -->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
                                        -->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation()
                                            -->调用AOP相关的后置处理器
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // ...
    
    // 注释大意: 实例化所有剩余的(非lazy-init)单例。
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons(); // 断点停在这里
}

finishBeanFactoryInitialization方法也需要注册Bean,它会调用preInstantiateSingletons方法遍历获取容器中所有的Bean,实例化所有剩余的、非懒加载初始化的单例Bean。

@Override
public void preInstantiateSingletons() throws BeansException {

  // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

  // Trigger initialization of all non-lazy singleton beans...
  for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 获取,非抽象、单例、非懒加载Bean
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          // 是否 是FactoryBean类型
          if (isFactoryBean(beanName)) {
              // ...
          }
          else {
              getBean(beanName); // 断点停在这
          }
      }
  }

  // ...
}

preInstantiateSingletons()方法通过调用getBean()方法获取Bean实例,执行过程为:

getBean()
    -->doGetBean()
    -->getSingleton()
    -->createBean()

又回到了上面registerBeanPostProcessors中注册Bean的步骤。这里要注意createBean方法中的resolveBeforeInstantiation方法,这里可以理解为缓存Bean,如果被创建了就拿来直接用,如果没有则创建Bean。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // ...
    try {
        // 注释大意:给 BeanPostProcessors 一个返回代理而不是目标bean实例的机会。
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 断点停在这里
        if (bean != null) {
            return bean;
        }
    }catch (Throwable ex){
       // ...
    }
    // ...

    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }catch (Throwable ex){
       // ...
    }
    // ...
    return null;
}

详细解析resolveBeforeInstantiation方法,其中关键是调用applyBeanPostProcessorsBeforeInstantiation方法。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 调用 applyBeanPostProcessorsBeforeInstantiation 方法
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 断点停在这
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

// ... 上面代码调用的方法 ...

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 遍历所有的 BeanPostProcessor
    for (BeanPostProcessor bp : getBeanPostProcessors()) {

        // //如果是 InstantiationAwareBeanPostProcessor 类型
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

            // 调用 postProcessBeforeInstantiation 方法
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); // 断点停在这
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

关键代码为ibp.postProcessBeforeInstantiation(beanClass, beanName),这里就是调用AnnotationAwareAspectJAutoProxyCreator组件的postProcessBeforeInstantiation方法。AnnotationAwareAspectJAutoProxyCreator组件实现了SmartInstantiationAwareBeanPostProcessor接口,所以bp instanceof InstantiationAwareBeanPostProcessor这行代码为true

AnnotationAwareAspectJAutoProxyCreator
    extends AspectJAwareAdvisorAutoProxyCreator
        extends AbstractAdvisorAutoProxyCreator
            extends AbstractAutoProxyCreator
                extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor,BeanFactoryAware
                    extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean 
SmartInstantiationAwareBeanPostProcessor 
    extends InstantiationAwareBeanPostProcessor
        extends BeanPostProcessor
postProcessAfterInitialization

AOP相关的后置处理器就是在postProcessBeforeInstantiation方法被调用的。上面的resolveBeforeInstantiation方法是createBean方法的调用栈,所以从层次结构上来看AnnotationAwareAspectJAutoProxyCreator组件的调用是在创建Bean实例之前,尝试用后置处理器返回对象的。一直往父类寻找,在其父类AbstractAutoProxyCreator实现了该方法。

@Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            //根据给定的bean的class和name构建出key,格式:beanClassName_beanName
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //一个非常核心的方法:wrapIfNecessary(),如果它适合被代理,则需要封装指定的bean。
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
}

其有一个非常核心的方法wrapIfNecessary(),这个方法就是代理创建的雏形。创建代理主要包含了两个步骤:获取增强方法或者增强器、根据获取的增强进行代理。

/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  //如果已经处理过
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
  }
  //这个bean无需增强
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
  }
  //判断给定的bean是否是一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要代理。
  //所谓InfrastructureClass就是指Advice/PointCut/Advisor等接口的实现类。
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
  }

  // 如果存在增强方法则创建代理
  //获取这个bean的advice
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  //如果获取到了增强则需要针对增强创建代理
  if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      //创建代理
      Object proxy = createProxy(
              bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
  }

  this.advisedBeans.put(cacheKey, Boolean.FALSE);
  return bean;
}

wrapIfNecessary方法中调用了getAdvicesAndAdvisorsForBean方法,该方法作用为获取增强方法或者增强器。调用栈为:

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
   -->AbstractAdvisorAutoProxyCreator.findEligibleAdvisors
   -->AbstractAdvisorAutoProxyCreator.findCandidateAdvisors
   -->BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans

BeanFactoryAdvisorRetrievalHelper这个类是一个Spring AOP内部工具类,用来从Bean容器中获取所有Spring的Advisor Bean。该工具内部使用了缓存机制,虽然公开的查找方法可能会被调用多次,但并不是每次都会真正查找,而是会利用缓存。

public List<Advisor> findAdvisorBeans() {
     //cachedAdvisorBeanNames是advisor名称的缓存
     String[] advisorNames = this.cachedAdvisorBeanNames;
     //如果cachedAdvisorBeanNames为空,则到容器中查找,并设置缓存,后续直接使用缓存即可
     if (advisorNames == null) {
         // Do not initialize FactoryBeans here: We need to leave all regular beans
         // uninitialized to let the auto-proxy creator apply to them!
         //从容器中查找Advisor类型的bean的名称
         advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                 this.beanFactory, Advisor.class, true, false);
         this.cachedAdvisorBeanNames = advisorNames;
     }
     if (advisorNames.length == 0) {
         return new ArrayList<>();
     }
   
     List<Advisor> advisors = new ArrayList<>();
     //遍历advisorNames
     for (String name : advisorNames) {
         if (isEligibleBean(name)) {
             //忽略郑州创建中的advisor bean
             if (this.beanFactory.isCurrentlyInCreation(name)) {
                 if (logger.isTraceEnabled()) {
                     logger.trace("Skipping currently created advisor '" + name + "'");
                 }
             }
             else {
                 try {
                     //调用getBean方法从容器中获取名称为name的bean,并将bean添加到advisors中
                     advisors.add(this.beanFactory.getBean(name, Advisor.class));
                 }
                 catch (BeanCreationException ex) {
                     Throwable rootCause = ex.getMostSpecificCause();
                     if (rootCause instanceof BeanCurrentlyInCreationException) {
                         BeanCreationException bce = (BeanCreationException) rootCause;
                         String bceBeanName = bce.getBeanName();
                         if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                             if (logger.isTraceEnabled()) {
                                 logger.trace("Skipping advisor '" + name +
                                         "' with dependency on currently created bean: " + ex.getMessage());
                             }
                             // Ignore: indicates a reference back to the bean we're trying to advise.
                             // We want to find advisors other than the currently created bean itself.
                             continue;
                         }
                     }
                     throw ex;
                 }
             }
         }
     }
     return advisors;
}

wrapIfNecessary方法中第二行关键的代码就是创建代理,调用了下面这行代码。

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
         @Nullable Object[] specificInterceptors, TargetSource targetSource) {

     if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
         AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
     }

     ProxyFactory proxyFactory = new ProxyFactory();
     //步骤1:获取当前类的属性。
     proxyFactory.copyFrom(this);

     //步骤2:添加代理接口。
     if (!proxyFactory.isProxyTargetClass()) {
         if (shouldProxyTargetClass(beanClass, beanName)) {
             proxyFactory.setProxyTargetClass(true);
         }
         else {
             evaluateProxyInterfaces(beanClass, proxyFactory);
         }
     }

     //步骤3:拦截器封装转化为增强器
     Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
     //步骤4:将Advisor加入到ProxyFactory中。
     proxyFactory.addAdvisors(advisors);
     //步骤5:设置要代理的类。
     proxyFactory.setTargetSource(targetSource);
     //步骤6:为子类提供了定制函数customizeProxyFactory
     customizeProxyFactory(proxyFactory);

     //步骤7:设置是否需要冻结代理对象。用来控制代理工厂被配置后,是否还允许修改通知。缺省值为false
     proxyFactory.setFrozen(this.freezeProxy);
     if (advisorsPreFiltered()) {
         proxyFactory.setPreFiltered(true);
     }

     //步骤8:进行代理操作。
     return proxyFactory.getProxy(getProxyClassLoader());
}

其中的关键代码是proxyFactory.getProxy(getProxyClassLoader()),作用是代理类的创建和处理。

public Object getProxy() {
    // 调用了ProxyCreatorSupport的createAopProxy()方法创建一个AopProxy对象
   // 然后调用AopProxy对象的getProxy方法
   return createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() {
  if (!this.active) {
      activate();
  }
  // 实际就是使用DefaultAopProxyFactory来创建一个代理对象
  // 可以看到在调用createAopProxy方法时,传入的参数是this
  // 这是因为ProxyCreatorSupport本身就保存了创建整个代理对象所需要的配置信息
  return getAopProxyFactory().createAopProxy(this);
}

createAopProxy通过AOP相关的配置信息来决定到底是使用CGLib代理还是JDK代理。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // 如果开启了优化,或者ProxyTargetClass设置为true
  // 或者没有提供代理类需要实现的接口,那么使用cglib代理
  // 在前面分析参数的时候已经说过了
  // 默认情况下Optimize都为false,也不建议设置为true,因为会进行一些侵入性的优化
  // 除非你对cglib的优化非常了解,否则不建议开启
  if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
          throw new AopConfigException("TargetSource cannot determine target class: " +
                  "Either an interface or a target is required for proxy creation.");
      }
      // 需要注意的是,如果需要代理的类本身就是一个接口
      // 或者需要被代理的类本身就是一个通过jdk动态代理生成的类
      // 那么不管如何设置都会使用jdk动态代理
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
          return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
  }
  // 否则都是jdk代理
  else {
      return new JdkDynamicAopProxy(config);
  }
}

AOP原理用的就是动态代理,而且在Spring中主要使用了两种动态代理:

  • JDK动态代理技术:JDK的动态代理时基于Java的反射机制来实现的,是Java 原生的一种代理方式。他的实现原理就是让代理类和被代理类实现同一接口,代理类持有目标对象来达到方法拦截的作用。通过接口的方式有两个弊端一个就是必须保证被代理类有接口,另一个就是如果相对被代理类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明。接口继承的是java.lang.reflect.InvocationHandler
  • CGLib动态代理技术:CGLib动态代理使用的ASM这个非常强大的Java字节码生成框架来生成class,基于继承的实现动态代理,可以直接通过super关键字来调用被代理类的方法,子类可以调用父类的方法,不要求有接口。
动态代理

代理是一种常见的设计模式,通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,可以在不修改目标对象的情况下,扩展其功能。代理模式包含三个主要角色:代理接口、目标对象、代理对象。代理模式分为静态代理和动态代理两种类型。静态代理在编译时由程序员手动创建或通过工具生成代理类,增加了代码量。动态代理在运行时动态生成代理类,包括JDK动态代理和CGLIB动态代理。

Spring默认采取的动态代理机制实现AOP,简单来说就是在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。JDK动态代理使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现,它只能代理实现了接口的类。

public interface Service {
    void perform();
}

public class RealService implements Service {
   @Override
   public void perform() {
      System.out.println("Executing perform method in RealService");
   }
}
public class ServiceInvocationHandler implements InvocationHandler {
    private final Object target;

    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method call");
        Object result = method.invoke(target, args);
        System.out.println("After method call");
        return result;
    }
}
public class Main {
    public static void main(String[] args) {
        Service realService = new RealService();
        ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);

        Service proxyService = (Service) Proxy.newProxyInstance(
                realService.getClass().getClassLoader(),
                realService.getClass().getInterfaces(),
                handler
        );
        proxyService.perform();
    }
}

CGLIB动态代理使用字节码生成技术,可以代理没有实现接口的类。它通过继承的方式创建代理类,因此不能代理final类。

<!--在pom.xml中添加以下依赖-->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
public class RealService {
    public void perform() {
        System.out.println("Executing perform method in RealService");
    }
}

public class ServiceMethodInterceptor implements MethodInterceptor {
   @Override
   public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
      System.out.println("Before method call");
      Object result = proxy.invokeSuper(obj, args);
      System.out.println("After method call");
      return result;
   }
}
public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealService.class);
        enhancer.setCallback(new ServiceMethodInterceptor());

        RealService proxyService = (RealService) enhancer.create();
        proxyService.perform();
    }
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值