Spring AOP
使用方式
以最简单的注释式AOP为例。
被代理类
@Service
public class PersonService {
public void exec() {
System.out.println("exec person method...");
}
}
切面类
@Component
@Aspect
public class PersonServiceAspect {
@Pointcut("execution(* base.spring.service.PersonService..*(..))")
public void point(){}
@Before("point()")
public void before(){
System.out.println("before");
}
@After("point()")
public void after(){
System.out.println("after");
}
}
启动类
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("base.spring")
public class AppConifg {
}
class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConifg.class);
context.getBean(PersonService.class).exec();
}
}
执行结果:
before
exec person method...
after
原理解析
@EnableAspectJAutoProxy导入相关类
点开EnableAspectJAutoProxy
的元注解信息。EnableAspectJAutoProxy
注解有两个参数:
- proxyTargetClass:强制使用CGLIB完成AOP代理;
- exposeProxy:用来解决同一个类里方法调用只生效一次的问题;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
查看@Import
导入的AspectJAutoProxyRegistrar
类
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//手动注册AOP代理过程中需要的类
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
...
// registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)
Debug跟进注释处,可以发现最终手动注册了AnnotationAwareAspectJAutoProxyCreator
类。
该类是SmartInstantiationAwareBeanPostProcessor
的子接口,即这个类将被作为后置处理器参与到Spring的初始化当中。
什么时候进行AOP代理?
首先可以明确:Spring是利用后置处理器实现AOP代理的(即上文提到的AnnotationAwareAspectJAutoProxyCreator
类)
Spring初始化(java config形式)的大体步骤可以概括为如下步骤:
- 先扫描类信息,然后转换成
BeanDefinition
并添加到BeanDefinitonMap
中; - 遍历
BeanDefinitonMap
,解析成创建时需要的描述信息(mergeBeanDefinition
); - 反射创建实例;
- 对实例进行属性填充(即创建实例内部的成员变量);
- 属性填充时,如果存在属性注入,则执行该属性的创建或者获取操作(未创建则创建,已创建则直接取);
- 完成属性填充
- 将该实例添加到Spring的单例池中,完成该类的初始化操作;
上述描述较为粗略,实际上比这个更细致,比如:
- 实际不是直接遍历
BeanDefinitionMap
; - 反射创建实例时需要推断构造器,通过后置处理器实现该功能;
- 通过后置处理器完成属性填充;
- 属性填充时可能发生循环依赖;
- 等等……
更多的内容可以看以下文章:
Spring的AOP代理自然是要参与到上面的这个步骤的,因为最终添加到Spring单例池中的势必是代理后的对象。
那么Spring是什么时候进行代理的呢?
第1种情况
在属性填充完毕,基本完成该类的实例化后,调用后置处理器的方法, 对该类进行AOP代理。即上面的6~7步之间
这种情况很好理解:初始化一个类的时候,该类的属性都初始化完了,那么就该对该类进行代理了,代理结束后,就可以添加该类到单例池中,最终完成该类的初始化。这个 ”后置处理器的方法“ 就是postProcessAfterInitialization
方法。
第2种情况
之所以还要提到第2种情况,是因为Spring的循环依赖问题。关于循环依赖,需要看上文提到的三级缓存方面的解析。举个例子
- A类的成员变量注入了B类,B类的成员变量注入了A类,先初始化A。
这是个典型的循环依赖。Spring通过三级缓存解决了这个问题。过程不再描述。下面考虑一下AOP的情况:
- 假定A类需要进行AOP代理(即通过
@Aspect、@PointCut、@Before
等注解识别到该类)
在新加入的这个前提下,初始化A时,需要初始化B,B需要获取A,然后因为A类处于创建中状态,然后从三级缓存里面获取到A类。
那么这个这被 B 类所需要的A 类怎么办?(说起来比较绕,为方便讲述,以AA来表示这个类)
首先是AA类一定需要经过代理,否则单例池中的B类所包含的AA类的AOP配置就失效了。那么通过B类调用AA类,就没有了AOP处理的逻辑。
Spring的处理方式:当出现循环依赖需要获取AA类的时候,通过第三级缓存:singletonFactories
调用后置处理器的getEarlyBeanReference
方法。
可以查看这两个方法,都调用了wrapIfNecessary
方法,wrapIfNecessary
就是判断当前类是否需要进行代理,需要则代理,不需要则跳过。
postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//避免无意义的调用代理逻辑,缓存的作用
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
getEarlyBeanReference
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
有几点需要注意:
getEarlyBeanReference
方法只有在出现循环依赖的时候才会被调用。- 不管有没有出现循环依赖都会调用
postProcessAfterInitialization
方法。 - 出现循环依赖的时候,调用
getEarlyBeanReference
的AOP处理逻辑,实际上就不需要调用postProcessAfterInitialization
的AOP处理逻辑了。因为已经代理过了一次,直接使用代理后的类即可。
为了避免无意义的逻辑调用,Spring使用三级缓存来解决了这个问题。
//AbstractAutoProxyCreator的成员变量:earlyProxyReferences,存储已经进行过代理的类。
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
//1. 一级缓存:单例池,即通常意义下的Spring容器,SpringBean最终到达的地方
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//2.二级缓存:存储提前完成了代理的类
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
//3.三级缓存:存储的ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
整理一下第2种情况的处理逻辑:
- 初始化A时,需要初始化B,B需要获取A,然后因为A类处于创建中状态,调用三级缓存
singletonFactories
的getObject
方法,间接调用getEarlyBeanReference
方法。 getEarlyBeanReference
方法内首先将当前A类(未被代理)存储到earlyProxyReferences
集合中,标注A类进行过代理了。- 执行完
getEarlyBeanReference
方法,代理创建AA类,将AA类存到二级缓存中; - B类所需要的A类(代理后的)创建完毕,结束B的创建。
- 回到A的创建,A执行
postProcessAfterInitialization
方法。需要注意当前的A并没有被代理。 - 从earlyProxyReferences移除并获取A类,与当前类进行对比,都是没被代理过得类,且是同一个对象,证明当前类已经进行过代理了。跳过
wrapIfNecessary
的判断逻辑。 - 继续A的创建,注意此时A实际还是没有代理。此时尝试从spring的一二三级缓存里面获取A,最终在二级缓存里面获取到了AA类(第3步是添加,如果没有发生循环依赖,这个时候应当无法从二级缓存里面获取到)
- 使用二级缓存里面的AA替换当前的A
- 完成A的初始化。
这一块儿的内容,删删改改不知道怎么说。确实也比较绕。建议多Debug一下。这里贴一下相关的方法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
...
}
if (earlySingletonExposure) {
//此处即是第7步,在这一步从二级缓存里面获取到了AA
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
//第8步,用AA替换A,完成A的初始化
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
...
}
}
}
}
...
return exposedObject;
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//出现循环依赖时,进入下面的判断
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//第7步,此时从二级缓存获取到了AA
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//三级缓存移到二级缓存,完成了AA的创建,第2~3步
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
wrapIfNecessary逻辑
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//判断当前类是否需要进行代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 创建代理
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;
}
createProxy
通过ProxyFactory创建代理。
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();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
getProxy
createAopProxy
来根据当前类创建合适的AOP工厂,即判断使用jdk动态代理还是cglib,分别对应JdkDynamicAopProxy
和CglibAopProxy
使用对应的AOP工厂完成代理。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}