Spring(十六):创建AOP代理

AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

}

//获取expose_proxy_attribute属性

//并且转为布尔类型

boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));

//判断是否开启

if (exposeProxy) {

//如果开启了强制对切面进行曝光

AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);

}

}

}

下面就来看看是怎么强制使用的

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {

if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {

//从注册容器中去取出AOP切面的BeanDefinition

BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);

//改变里面的属性

definition.getPropertyValues().add(“proxyTargetClass”, Boolean.TRUE);

}

}

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {

if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {

//从注册容器中去取出AOP切面的BeanDefinition

BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);

//改变里面的属性

definition.getPropertyValues().add(“exposeProxy”, Boolean.TRUE);

}

}

可以看到,强制使用仅仅只是改变注册容器里面的AOP切面的BeanDefinition里面的属性

现在已经完成了AOP自动创建器的注册了,本来AOP自动创建器在Spring中的存储形式也是一个BeanDefinition,所以也需要注册后才能使用

创建AOP代理


上面已经将AOP自动创建器注册了,那么这个类到底做了什么工作来完成AOP的操作呢?接下来我们就对这个AnnotationAwareAspectJAutoProxyCreator进行分析

AnnotationAwareAspectAutoProxyCreator的架构

首先我们对这个类的整体架构进行分析

在这里插入图片描述

其关系大概是这样的

AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,AspectJAwareAdvisorAutoProxyCreator又继承了AbstractAdvisorAutoProxyCreator,而AbstractAdvisorAutoProxy又继承了AbstractAutoProxyCreator

这个类实现了BeanPostProcessor接口,前面我们看Bean进行加载的时候,会去调用其PostProcessAfterInitialization方法(之前跳过了没去分析,所以现在知道了那个方法是针对切面类的BeanDefinition来进行处理的)

postProcessAfrerInitialization方法却是在AbstractAutoProxyCreator来实现的

源码如下

@Override

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {

//判断传进来的Bean是否为空

if (bean != null) {

//获取缓存的键名,这里的形式是beanClassName_beanName

Object cacheKey = getCacheKey(bean.getClass(), beanName);

//判断是否已经提前曝光代理过

if (this.earlyProxyReferences.remove(cacheKey) != bean) {

//如果没被代理过,执行wrapIfNecessart

return wrapIfNecessary(bean, beanName, cacheKey);

}

}

//如果bean为Null,直接返回,如果不为null,但已经被曝光出来,直接返回bean

//解决了循环依赖的问题

return bean;

}

关键还是在于wrapIfNecessary方法上

wrapIfNecessary

该方法的作用就是进行给BeanDefinition进行代理增强的,并且会先判断有没有必要进行代理增强

源码如下

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

//判断是不是已经增强过

//即targetSourcedBeans容器里面已经包含了这个BeanDefinition

if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {

//如果已经增强过,直接返回

return bean;

}

//判断是不是无需进行增强

//如果不位于advisedBeans里面,代表无需进行增强

//因为每个Bean加载的时候都会进入这个方法,切面的Bean肯定比事务的Bean少

//所以会将创建切面的Bean都存进advisedBeans容器中

if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {

//如果不需要增强,返回结果

return bean;

}

//判断该BeanDefinition是不是基础设施类,如果是基础设施类并且需要跳过

if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {

//在advusedBeans容器中去存储该BeanDefinition

this.advisedBeans.put(cacheKey, Boolean.FALSE);

//value改为false,这也是前面第二个if判断的清空,如果是基础设施

return bean;

}

// Create proxy if we have advice.

//来到这里就证明需要给这个类建立切面了

//如果存在增强方法则要创建代理

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

//判断是否存在增强方法,这里DO_NOT_PROXY是一个Null

if (specificInterceptors != DO_NOT_PROXY) {

//如果存在增强方法

//将

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值