开启AOP相关注解,xml中配置如下:
<aop:aspectj-autoproxy />
1、AOP 相关组件注册
spring容器启动时,将会解析配置文件中的指令节点逐一解析,配置了aspectj-autoproxy指令后,在refresh()
中的obtainFreshBeanFactory()
阶段解析XML配置时,当解析到该指令时,触发AspectJAutoProxyBeanDefinitionParser
解析器对其进行解析。
主要由AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
注册AOP相关注解组件并通知,便于监听器进一步处理。
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册或升级AutoProxyCreator定义beanName为
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件并通知,便于监听器进一步处理
//其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
2、AOP 创建代理
在上文组件注册章节中已经完成了AnnotationAwareAspectJAutoProxyCreator.class
类型的bean注册。在其类层次结构中看出实现了BeanPostProcessor
接口,即等于是bean的增强器。
所以我们只需关注bean初始化前后的两个增强逻辑(postProcessBeforeInitialization
,postProcessAfterInitialization
)即可。
2.1、postProcessBeforeInstantiation方法:
在该方法中,首先判断是否被处理,若被处理,则判断设置是否代理,紧接着判断是否基础设施类或者是否需要跳过该bean,而跳过逻辑中:根据切点增强方法中的切面名称是否和该bean name一致,一致则跳过。
若未被处理,则根据自定义bean creator创建bean,最后根据切面中方法判断是否要创建该bean代理。
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
// 如果已经被处理过
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
注意:跳过判断方法中解析了切面中的方法,并添加缓存。下方贴出shouldSkip()
代码:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
//若和切面名称一致,则跳过,无需创建代理类
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 当时用注解方式配置AOP时,并不是丢弃了对XML的支持
// 在这里调用父类方法加载配置中的AOP声明
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
//double check lock
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//获取所有的bean names
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
Class<?> beanType = this.beanFactory.getType(beanName);
// 如果存在aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 解析标记AspectJ注解中的 增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
advisors.addAll(classAdvisors);
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
return advisors;
}
/**
* 解析 标记AspectJ注解bean中的 增强方法
*/
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取标记AspectJ的类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取标记AspectJ的切面名称
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
List<Advisor> advisors = new ArrayList<>();
// getAdvisorMethods(aspectClass) 获取所有切面中非@PiontCut的方法
for (Method method : getAdvisorMethods(aspectClass)) {
/**
* 1、获取普通增强器的逻辑
* 1.1、对切点的注解的获取
* 1.2、根据不同的注解信息生成不同的增强(before、around、after...)
*/
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
总之:在bean初始化前的增强逻辑中,就会把所有的切面及切面内的增强方法全部解析完成,并加入缓存LIST中,为后续的bean后置增强中创建代理提供支持。
2.2 postProcessAfterInitialization方法
bean的后置增强,则是在初始化bean属性后,如果需要代理,则返回代理后的bean。
🎈在这之前先介绍实例化的初始化(initializeBean
)阶段,在此阶段将执行bean前置和后置逻辑增强。代码如下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 前置增强
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
// 后置增强——在此处生成代理类如果需要的话
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
后置增强方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果适合被代理,则需要封装指定bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary方法
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,不需要自动代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have 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;
}
针对不同的模式选择是JDK代理还是CGLIB代理。
该类是否继承接口,存在接口继承则使用JDK代理(生成接口的代理实现类),否则使用CDLIB进行代理(生成完成继承该类所有非final方法的兄弟类)。
注意:若是当前bean不存在实现接口,则直接采用CGLIB生成代理。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
后续学习深入后再进行补充!!!