Spring AOP源码分析

启动Spring AOP需要配置 <aop:config> 标签或者aspectj-autoproxy标签

<aop>标签解析

如果使用<aop:xxxx />标签来自动生成代理的话,入口程序是AopNamespaceHandler

1
2
3
4
5
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
}
  • 如果使用了<aop:config>标签,使用 ConfigBeanDefinitionParser 解析
  • 如果使用了<aop:aspectj-autoproxy>标签,使用 AspectJAutoProxyBeanDefinitionParser 解析

类结构图

这里放一张Spring AOP代理自动生成器的类图

  • <aop:config>方式使用AspectJAwareAdvisorAutoProxyCreator创建代理,`
  • <aop:aspectj-autoproxy>使用AnnotationAwareAspectJAutoProxyCreator创建代理,具体见下文

img

aop:config`解析

  • ConfigBeanDefinitionParser.java
1
2
3
4
5
6
7
8
9
10
11
12
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 注册AspectJAwareAdvisorAutoProxyCreator
configureAutoProxyCreator(parserContext, element);
}
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
  • AopNamespaceUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册或更新 AutoProxyCreator 定义 beanName 为 org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
// 如果internalAutoProxyCreator的BeanDefinition已经存在,则根据优先级更新BeanDefinition
// 在这里注册的是AspectJAwareAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件,其中beanDefinition的className为AspectJAwareAdvisorAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
  • AspectJAwareAdvisorAutoProxyCreator.java
1
2
3
4
5
6
7
8
9
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyConfig
implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
Ordered, AopInfrastructureBean
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor

可见AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口,BeanPostProcessor主要作用于Bean实例化后,初始化前后,所有的Bean都被作用到。InstantiationAwareBeanPostProcessor虽然是BeanPostProcessor的子接口,但它的调用时间点发生在Bean实例化前,在真正调用doCreateBean()创建bean实例之前执行postProcessBeforeInstantiation()

  • postProcessBeforeInstantiation()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
//1、得到一个缓存的唯一key(根据beanClass和beanName生成唯一key)
Object cacheKey = getCacheKey(beanClass, beanName);
//2、如果当前targetSourcedBeans(通过自定义TargetSourceCreator创建的TargetSource)不包含cacheKey
if (beanName == null || !this.targetSourcedBeans.containsKey(beanName)) {
//2.1、advisedBeans(已经被增强的Bean,即AOP代理对象)中包含当前cacheKey,返回null,即走Spring默认流程
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//2.2、如果是基础设施类(如Advisor、Advice、AopInfrastructureBean的实现)不进行处理
//2.2、shouldSkip 默认false,可以生成子类覆盖,如AspectJAwareAdvisorAutoProxyCreator覆盖(if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) return true; 即如果是自己就跳过)
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//3、开始创建AOP代理对象
if (beanName != null) {
//3.1、配置自定义的TargetSourceCreator进行TargetSource创建
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//3.2、如果targetSource不为null 添加到targetSourcedBeans缓存,并创建AOP代理对象
if (targetSource != null) {
this.targetSourcedBeans.put(beanName, Boolean.TRUE);
// specificInterceptors即增强(包括前置增强、后置增强等等)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//3.3、创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
//3.4、将代理类型放入proxyTypes从而允许后续的predictBeanType()调用获取
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}

当我们配置TargetSourceCreator进行自定义TargetSource创建时,会创建代理对象并中断默认Spring创建流程(目标对象没有创建,可见bean创建过程: BeanDefinitionValueResolver.resolveInnerBean())。

  • getEarlyBeanReference()

Spring Bean实例化过程,解决单例bean之间的循环依赖问题,提前将代理对象暴露出去

1
2
3
4
5
6
7
8
9
// AbstractAutoProxyCreator.java
//获取early Bean引用(只有单例Bean在创建)
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//1、将cacheKey添加到earlyProxyReferences缓存,从而避免多次重复创建
this.earlyProxyReferences.add(cacheKey);
//2、包装目标对象到AOP代理对象(如果需要)
return wrapIfNecessary(bean, beanName, cacheKey);
}

详细可见bean创建过程:AbstractAutowireCapableBeanFactory.doCreateBean() => getEarlyBeanReference()

  • postProcessAfterInitialization():创建AOP代理

默认情况下,代理是通过AbstractAutoProxyCreator中的postProcessAfterInitialization()创建的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// AbstractAutoProxyCreator.java
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//1、如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
//2、包装目标对象到AOP代理对象(如果需要)
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//通过TargetSourceCreator进行自定义TargetSource不需要包装
if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
return bean;
}
//不应该被增强对象不需要包装
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//基础设施或应该skip的不需要保证
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) {
// 将cacheKey添加到已经被增强列表,防止多次增强
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;
}

可以看出 getEarlyBeanReferencepostProcessAfterInitialization是二者选一的,而且单例Bean目标对象只能被增强一次

SimpleServiceImpl bean初始化到这步后,会从容器中找出所有匹配当前bean的通知(如果有对业务方法做增强处理),如果找到对应的通知则创建代理。

  • createAopProxy()

具体怎么创建代理以及用哪种方式创建代理,由 createAopProxy 决定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果没有实现接口或者设置proxy-target-class=true, 采用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.");
}
// 如果目标类是接口, 使用JDK动态代理来生成代理类
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}

aspectj-autoproxy标签解析

  • AspectJAutoProxyBeanDefinitionParser.java
1
2
3
4
5
6
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
  • AopNamespaceUtils.java
1
2
3
4
5
6
7
8
9
10
11
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册或更新 AutoProxyCreator 定义 beanName 为 org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
// 如果internalAutoProxyCreator的BeanDefinition已经存在,而根据优先级更新BeanDefinition
// 在这里注册的是AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件
registerComponentIfNecessary(beanDefinition, parserContext);
}
  • AnnotationAwareAspectJAutoProxyCreator.java
1
2
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
}

可以发现AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator, 执行流程和aop:config基本一致,但是需要注意注解的特殊标签@Aspect,下面分析@Aspect注解是如何起作用的?

使用注解配置AOP,需要在切面类中配置@Aspect,再来看看AOP代理生成过程:

1
2
3
4
5
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 获取该类所有增强
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
}

不管是aop:config还是aspectj-autoproxy都是由AbstractAutoProxyCreator这个类在后置处理器中生成AOP代理,具体看看getadvicesAndAdvisorsForBean()方法是如何获取增强

  • getAdvicesAndAdvisorsForBean()

getAdvicesAndAdvisorsForBean()方法具体由子类AbstractAdvisorAutoProxyCreator实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// AbstractAdvisorAutoProxyCreator.class
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到容器中所有增强
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从所有增强中找出指定类(正常业务类)的增强
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}

这里的findCandidateAdvisors方法,如果配置aop:config则由AbstractAdvisorAutoProxyCreator本类中实现,如果配置aspectj-autoproxy则由AnnotationAwareAspectJAutoProxyCreator子类中实现。现在来看看子类实现:

  • findCandidateAdvisors()
1
2
3
4
5
6
7
8
// AnnotationAwareAspectJAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
// 当使用注解方式配置AOP的时候并不是丢弃了对xml的配置,调用父类加载配置文件中的AOP声明
List<Advisor> advisors = super.findCandidateAdvisors();
// 如果使用了aspectJ注解配置aop
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}

从方法中aop可以配置在xml中,同时也可以使用注解,2这都会同时生效。

目标对象

  • 配置增强
1
2
3
4
5
6
7
8
9
@Aspect
public class DoBeforeAspect {
@Before("execution(* com.zsr.test.aop.SimpleService.sayHello(..))")
public void doBefore(JoinPoint joinPoint) {
System.out.println("***AspectJ*** DoBefore() is running!! intercepted : " + joinPoint.getSignature().getName());
}
}
  • 业务逻辑
1
2
3
4
5
6
7
8
9
@Component("simpleService")
public class SimpleServiceImpl implements SimpleService {
@Override
public String sayHello(String message) {
System.out.println("SimpleService : Method sayHello() : Hello " + message);
return message;
}
}

测试发现当配置了增强后,再去容器中获取目标bean,结果该bean其实是个代理,代理最终还是要通过执行invoke()方法调用目标对象的sayHello()方法,那么目标对象到底放在什么地方?

代理模式

下面是代理模式的结构:

img

  • Subject:抽象主题,它是代理对象的真实对象要实现的接口,当然这可以是多个接口组成
  • Proxy:代理类除了实现抽象主题定义的接口外,还必须持有所代理对象的引用
  • RealSubject:被代理的类,是目标对象

JdkDynamicAopProxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/** Config used to configure this proxy */
private final AdvisedSupport advised;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里会去执行增强和目标对象方法
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
}
}

需要注意JdkDynamicAopProxy持有的AdvisedSupport实例,AdvisedSupport类中包含了一个TargetSource实例,目标对象就在TargetSource中,也就是说代理间接持有了目标对象

1
2
3
public class AdvisedSupport extends ProxyConfig implements Advised {
TargetSource targetSource = EMPTY_TARGET_SOURCE;
}

回过头来,再看看动态代理的创建过程

1
2
3
4
5
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 创建代理对象
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}

看到这里的SingletonTargetSource就是TargetSource的实现类,其实在创建代理的时候就已经把目标对象放到TargetSource中,换句话说,proxy(代理对象)代理的不是target,而是TargetSource

注意:

  • 目标bean的生命周期不受Spring容器管理,我们以往的XML中的AOP配置,只是对受容器管理的bean而言的
  • 代理类会代理接口中所有方法,非增强方法同样需要通过代理类去访问(只是没有执行增强切面)
  • SpringAOP框架默认为目标bean创建静态目标源SingletonTargetSource,如果bean被配置为prototype,则spring会在每次getBean时创建新的SingletonTargetSource实例

参考

Spring AOP源码解读1 - 程序入口

spring-aop组件详解——TargetSource目标源

Spring源码-AOP(七)-增强器的获取

Spring开闭原则的表现-BeanPostProcessor扩展点-2

Spring内部的BeanPostProcessor接口总结

热评文章