1. Spring AOP概述
Spring AOP(Aspect-Oriented Programming)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,为业务逻辑添加额外的功能,如日志、事务管理、权限验证等。这些额外的功能被称为“切面”,它们会切入到类的指定方法上,在方法执行前后或出现异常时执行特定的代码。
2. Spring AOP的代理实现
Spring AOP的代理主要有两种实现方式:JDK动态代理和CGLIB动态代理。
- JDK动态代理:要求被代理的类必须实现一个或多个接口。Spring AOP通过反射机制创建代理对象,代理对象持有目标对象的引用,并在调用目标对象的方法时,动态地插入切面逻辑。
- CGLIB动态代理:如果目标类没有实现任何接口,Spring AOP会使用CGLIB库来创建代理对象。CGLIB通过继承目标类来创建代理,因此代理对象会拥有目标类的所有非final方法。
3. Spring AOP代理生命周期深度解析
- 准备阶段:
- 扫描和识别:Spring容器在启动时,会扫描所有的Bean定义,查找标记有AOP相关注解(如@Aspect)的Bean以及需要通过AOP增强的Bean。
- 注册切面:对于被标记为切面的Bean,Spring会解析其中的通知(Advice)和切入点(Pointcut)定义,并将它们注册到相应的切面信息中。
- 代理创建阶段:
- 判断代理类型:Spring根据被代理的Bean是否实现了接口,决定使用JDK动态代理还是CGLIB代理。如果Bean实现了接口,则使用JDK动态代理;否则,使用CGLIB代理。
- 创建代理对象:
- 对于JDK动态代理,Spring通过
java.lang.reflect.Proxy
类的newProxyInstance
方法创建代理对象,该方法需要传入类加载器、接口数组和InvocationHandler
接口的实现类。 - 对于CGLIB代理,Spring使用CGLIB库来创建代理对象。它首先会生成目标类的子类,并在子类中覆盖目标方法,加入代理逻辑。
- 对于JDK动态代理,Spring通过
- 封装目标对象:在代理对象内部,Spring会持有目标对象的引用,以便在调用目标方法时能够找到真正的执行者。
- 代理初始化阶段:
- 依赖注入:如果代理对象需要依赖其他Bean,Spring会负责将这些依赖注入到代理对象中。
- 通知织入:Spring会根据注册的切面和切入点信息,将通知(Advice)织入到代理对象中。这通常是通过修改代理对象的字节码来实现的,以便在调用目标方法时能够执行通知中的代码。
- 代理使用阶段:
- 当其他Bean通过代理对象调用目标方法时,Spring会拦截这个调用,并根据织入的通知执行相应的代码。这可能包括在目标方法执行前、后或出现异常时执行特定的逻辑。
- 代理销毁阶段:
- 当Spring容器关闭时,它会销毁所有的Bean,包括代理对象。在销毁之前,Spring会执行一些清理工作,如关闭资源、释放连接等。
4. 源码分析
在Spring的源码中,与AOP代理生命周期相关的关键类包括:
- AspectJAutoProxyRegistrar:这个类用于在Spring容器中注册
AnnotationAwareAspectJAutoProxyCreator
Bean,它是实现AOP特性的核心后置处理器。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 注册AnnotationAwareAspectJAutoProxyCreator Bean AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); }
} // 在AopConfigUtils中
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { // 检查是否已注册 // ... // 如果没有注册,则注册AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition beanDefinition = new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class); // ... 设置bean定义属性 registry.registerBeanDefinition(AOP_AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
}
- AnnotationAwareAspectJAutoProxyCreator:这个类继承自
AbstractAutoProxyCreator
,并实现了BeanPostProcessor
接口。它负责在Bean的创建过程中创建代理对象,并织入切面逻辑。
public class AnnotationAwareAspectJAutoProxyCreator extends AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { // ... 省略其他代码 ... @Override protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 判断是否需要创建代理 if (shouldSkip(beanName, bean, cacheKey)) { return bean; } // 创建代理对象 ProxyFactory proxyFactory = createProxyFactory(bean); return proxyFactory.getProxy(); } // ... 省略其他代码,如postProcessAfterInitialization、findEligibleBeans等 ...
} // 在ProxyFactory中
public Object getProxy() { return createAopProxy().getProxy();
} // 在AopProxyFactory中
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 判断是否实现了接口,从而决定使用JDK动态代理还是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."); } // 创建CGLIB代理 return new ObjenesisCglibAopProxy(config); } else { // 创建JDK动态代理 return new JdkDynamicAopProxy(config); }
}
在AnnotationAwareAspectJAutoProxyCreator
的源码中,可以看到它是如何扫描切面、注册通知和切入点、创建代理对象以及织入通知的。
- ProxyFactory:这个类是一个用于创建AOP代理的工厂类,它提供了创建JDK动态代理和CGLIB代理的接口。
public class ProxyFactory { private AdvisedSupport advisedSupport; // 假设这是一个包含代理配置的类 public ProxyFactory(AdvisedSupport advisedSupport) { this.advisedSupport = advisedSupport; } public Object getProxy() { // 判断是否应该使用CGLIB代理或JDK动态代理 boolean proxyTargetClass = advisedSupport.isProxyTargetClass(); boolean hasInterfaces = !Proxy.isProxyClass(advisedSupport.getTargetClass()) && advisedSupport.getTargetClass() != null && advisedSupport.getTargetClass().getInterfaces().length > 0; // 如果没有指定使用CGLIB并且目标类有接口,则使用JDK动态代理 if (!proxyTargetClass && hasInterfaces) { return new JdkDynamicAopProxy(advisedSupport).getProxy(); } // 否则,使用CGLIB代理 return new CglibAopProxy(advisedSupport).getProxy(); } // 这里为了简化,没有展示JdkDynamicAopProxy和CglibAopProxy的实现 // 但在Spring中,这些类会负责创建实际的代理对象 // 假设的AdvisedSupport类(为了演示) static class AdvisedSupport { private Class<?> targetClass; private boolean proxyTargetClass; // 省略getter和setter方法 public Class<?> getTargetClass() { return targetClass; } public void setTargetClass(Class<?> targetClass) { this.targetClass = targetClass; } public boolean isProxyTargetClass() { return proxyTargetClass; } public void setProxyTargetClass(boolean proxyTargetClass) { this.proxyTargetClass = proxyTargetClass; } }
}
通过查看ProxyFactory
的源码,可以了解代理对象的具体创建过程。
5. 总结
Spring AOP通过动态代理技术为业务逻辑添加了额外的功能,其代理生命周期包括准备、创建、初始化、使用和销毁五个阶段。在源码层面,Spring通过一系列关键的类(如AspectJAutoProxyRegistrar
、AnnotationAwareAspectJAutoProxyCreator
和ProxyFactory
)来实现AOP代理的创建和管理。通过深入理解这些类和源码实现,我们可以更好地掌握Spring AOP的原理和使用方法,从而更加灵活地应对各种复杂的业务场景。