Spring AOP 源码详解
在实际开发过程中,会有需要用到自动事务管理,自动日志打印等需求,那么通过一个注解或者配置,实现自动对类进行功能增强就非常有必要。Spring Aop就提供了这样的功能,实现对目标类的成员方法进行增强
SpringAop和AspectJ二者的关系
1、AspectJ是一个面向切面的Java框架,他定义了一套切面语言,如@Aspect、@Before、@AfterReturning、@AfterThrowing、@After、@Around等,还提供了强大的切面表达式,如(如@PointCut execution(* com.example.service..(…))),提供了强大的切面解析框架。
2、SpringAop提供了创建代理的能力,Spring定义了两个重要的核心接口,Advisor(PointCut+Advice通知)的组合,定义了在哪个类哪个方法增强哪个方法及增强逻辑,Advice是一个包含通知逻辑的拦截器,等同于AspectJ里的@Before等注解的实际类型。
同时Spring通过ProxyFactory代理工厂来创建目标类型的代理,可以选择(CglibAopProxy\JdkAopProxy)两种代理,我们一般在启动类配置@EnableAspectJAutoProxy(proxyTargetClass =true) // 强制使用CGLIB代理 不需要接口 生成被代理类的子类
代理工厂类:DefaultAopProxyFactory.java
/**
* 决定是JDK动态代理 还是CGLIB
* config.isProxyTargetClass() ->
* 最关键的开关(由 @EnableAspectJAutoProxy(proxyTargetClass = true)控制) 是否开启CGLIB 默认值false
* @param config the AOP configuration in the form of an
* AdvisedSupport object
* @return
* @throws AopConfigException
*/
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
这样两个组件的分工协作实现了完整的AOP功能
SpringAop增强的过程
1、创建代理的入口
有循环依赖的类和正常的类,AOP代理生成位置不一样。
有循环依赖,代理生成位置在获取早期bean引用的方法里:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
这里会有一个BeanPostPorcessor,AnnotationAwareAspectJAutoProxyCreator,类里面的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);
}
没有循环依赖
代理生成的位置在调用完初始化方法,后置处理器里
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这里有一个BeanPostProcessor,AbstractAutoProxyCreator,这个类和上面的类是父子关系,调用的方法也一样,可以看到,最终都是调用wrapIfNecessary方法来创建代理
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
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;
}
2、获取切面类,判断当前目标类需不需要代理,(切面类不需要代理,没有切入规则的类不需要代理),上面两个生成代理方法的里面都有个关键逻辑
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
isInfrastructureClass(beanClass)用来判断当前类是不是切面的子类
shouldSkip(beanClass, beanName)
就是关键的解析切面类,判断切入规则
AspectJAwareAdvisorAutoProxyCreator.class
@Override
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);
}
findCandidateAdvisors() 就是查找所有的切面类
AspectJAwareAdvisorAutoProxyCreator.class
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
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;
}
buildAspectJAdvisors() 方法进行真正的切面解析
/**
* 寻找当前bean工厂注解了AspectJ注解的类,并返回aop切面列表代表他们
*/
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList

最低0.47元/天 解锁文章
1429

被折叠的 条评论
为什么被折叠?



