源码分析基于spring 4.3.x
一个小栗子
定义一个服务接口
package com.spring.start.service;
public interface IBlogService {
int getBlogCount();
}
接口实现类
package com.spring.start.service;
public class BlogService implements IBlogService {
@Override
public int getBlogCount() {
int count = 123;
System.out.println("blog count : " + count);
return count;
}
}
定义一个切面(Aspect)
@Aspect
public class LogAspect {
@Around("execution(public * com.spring.start..*.*.*(..))")
public Object methodAroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("log1 : start method");
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("log2 : end method");
return result;
}
@Around("execution(public * com.spring.start..*.*.*(..))")
public Object methodAroundLog2(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("log2 : start method");
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("log2 : end method");
return result;
}
}
切面类中定义了两个通知(Advice)methodAroundLog和methodAroundLog2,对com.spring.start下所有子包中所有类的所有pubic方法进行拦截,并输出写简单的log信息。
来看看配置文件application.xml
<!-- 开启aop -->
<aop:aspectj-autoproxy/>
<!-- 定义切面 -->
<bean id="logAspect" class="com.spring.start.aop.LogAspect"></bean>
<!-- 定义service -->
<bean id="blogService" class="com.spring.start.service.BlogService"></bean>
测试方法
public static void main(String[] args) {
ApplicationContext beanFactory = new ClassPathXmlApplicationContext("application.xml");
IBlogService blogService = beanFactory.getBean("blogService", IBlogService.class);
blogService.getBlogCount();
}
输出结果:
log1 : start method
log2 : start method
blog count : 123
log2 : end method
log2 : end method
可以看到aop已成功拦截到了方法,并输出了对应的log。
一开始,先明确几个概念
aspect:切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的
advice:通知,表示一个method执行前或执行后的动作。上面栗子中定义了两个环绕通知
pointcut:切入点,表示根据method的名字或者正则表达式去拦截一个method。
advisor:只有一个通知和一个切入点的切面,可以看做一种特殊的aspect
开始阅读源码前,我比较关注的几个问题:
-
<aop:aspectj-autoproxy/>
的作用 - spring如何根据Aspect注解创建切面
- spring如何根据切面信息创建代理对象
- 上面定义的两个通知methodAroundLog和methodAroundLog2,spring是如何进行链式调用的
<aop:aspectj-autoproxy/>
的作用
aspectj-autoproxy是spring自定义的标签。我们知道,在spring中自定义标签,需要编写一个继承于NamespaceHandlerSupport的类来实现标签解析工作。
在github spring源码中搜索一下,就可以发现aspectj-autoproxy的解析类是AopNamespaceHandler:
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
而AspectJAutoProxyBeanDefinitionParser类负责对aspectj-autoproxy标签进行解析:
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
这里AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 会调用到AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
这里可以看到一个关键的类AnnotationAwareAspectJAutoProxyCreator,该类负责创建切面,registerOrEscalateApcAsRequired就是把该类注入到spring上下文环境中,以便后面使用。
创建切面
我们知道,spring中提供了BeanPostProcessor扩展接口,该接口有两个方法postProcessBeforeInitialization和postProcessAfterInitialization,实现该接口这两个方法,就可以在spring完成Bean的实例化前后添加自己的逻辑处理。
上面提到的AnnotationAwareAspectJAutoProxyCreator类,继承自AbstractAutoProxyCreator类,并实现了BeanPostProcessor。

AbstractAutoProxyCreator定义了自动拦截的逻辑,由子类来定义bean是否被代理的策略,例如,按类型,名称,定义细节等。
AbstractAdvisorAutoProxyCreator是通用自动代理创建器,会为每个检测到Advisor的bean构建AOP代理。
来看看AbstractAutoProxyCreator.postProcessAfterInitialization(spring会在目标bean生成后调用该方法)
public Object postProcessAfterInitialization(Object bean, String beanName) ... {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
主要逻辑在wrapIfNecessary:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// 创建Advices和Advisors
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;
}
getAdvicesAndAdvisorsForBean正是提供给子类创建通知的方法,该方法会调用子类AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean,再调用的它的findEligibleAdvisors方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 创建Advisors
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 过滤Advisors
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 扩充
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
这是一个非常重要的方法,实现了几个关键步骤
- findCandidateAdvisors 查找Advisors(第一次会创建)
- findAdvisorsThatCanApply 根据目标bean的class过滤一部分的Advisors
- extendAdvisors 扩充Advisors,spring会根据需要添加一些内部的Advisors
- sortAdvisors 对Advisors排序
findCandidateAdvisors 查找Advisors
findCandidateAdvisors方法负责找到所有的Advisors,该方法会调用到子类AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
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.
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()是创建Advisor的关键,来看看BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
```java
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
// 获取所以的bean
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);
// 获取Aspect元数据
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 创建AspectInstanceFactory
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 创建Advisors
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
} else {
...
}
}
}
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 构建结果
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
PerClauseKind是aspect的初始化模式,这里只展示了SINGLETON模式的创建, 可以参考 aspect api
这里可以看到一个简单的单例模式,如果当前的aspectBeanNames为null,会创建Advisors,并保存在advisorsCache中,以后每次都从advisorsCache取出advisors。
可以看到,如果一个类有Aspect注解,就会创建AspectInstanceFactory,并通过AspectJAdvisorFactory创建Advisors
而this.advisorFactory.getAdvisors(factory)
将会调用到ReflectiveAspectJAdvisorFactory.getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 切面类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<Advisor>();
// getAdvisorMethods会获取没有Pointcut注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 创建Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
...
return advisors;
}
// 创建Advisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 获取切入点Pointcut
AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 创建Advisor,Advisor中包含了pointcut和adviceMethod
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
// 获取切入点Pointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 获取Before, Around, After, AfterReturning, AfterThrowing, Pointcut注释
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 生成AspectJExpressionPointcut,该类记录了Aspect表达式
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
getAdvisorMethods
方法会获取所有没有Pointcut注释的方法,而getAdvisor
方法会对有Before, Around, After, AfterReturning, AfterThrowing注释的方法,创建InstantiationModelAwarePointcutAdvisorImpl,InstantiationModelAwarePointcutAdvisorImpl中有Advisor上下文的信息,如拦截方法aspectJAdviceMethod,切入点Pointcut等。
findAdvisorsThatCanApply 过滤Advisors
findAdvisorsThatCanApply方法,会过滤部分的Advisors
这里会检查目标bean的class和class中是否有方法可以匹配Advisor,如果没有则过滤。代码比较繁琐,不展开了
extendAdvisors(eligibleAdvisors) 扩充Advisors
看看AspectJAwareAdvisorAutoProxyCreator.extendAdvisors
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
...
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
// 添加ExposeInvocationInterceptor
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
spring会在advisors 列表开始位置添加ExposeInvocationInterceptor。
创建代理
我们知道,spring通过动态代理类实现aop,有jdk动态代理和cglib两种方法。
如果要使用jdk动态代理,被代理类必须实现一个接口。
为了避免在这里额外介绍cglib,我在上面的小栗子中让spring生成的BlogService实现了一个接口,这样我们来看一下jdk动态代理如何实现aop
创建代理
我们知道,spring通过动态代理类实现aop,有jdk动态代理和cglib两种方法。
如果要使用jdk动态代理,被代理类必须实现一个接口。
为了避免在这里额外介绍cglib,我在上面的小栗子中让spring生成的BlogService实现了一个接口,这样我们来看一下jdk动态代理如何实现aop
回顾AbstractAutoProxyCreator.wrapIfNecessary方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 构建Advisors
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;
}
}
getAdvicesAndAdvisorsForBean已经讲解(getAdvicesAndAdvisorsForBean已经查找了Advices和Advisors,buildAdvisors只是做一些检查,转换处理,如将Advices转换成Advisor),
这里来看看动态代理创建过程AbstractAutoProxyCreator.createProxy
protected Object createProxy(
...
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 存储Advisor
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory.getProxy
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
调用父类ProxyCreatorSupport.createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
注意,getAopProxyFactory().createAopProxy(this)
中参数是this,proxyFactory将自身作为参数(proxyFactory存储着Advisor),调用DefaultAopProxyFactory.createAopProxy
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);
}
}
可以看到,spring会根据用户配置和目标bean是否有实现接口,来决定使用JdkDynamicAopProxy或ObjenesisCglibAopProxy
来看看JdkDynamicAopProxy.getProxy
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
注意:Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
第三个参数是JdkDynamicAopProxy.this,JdkDynamicAopProxy实现了InvocationHandler
链式调用
JdkDynamicAopProxy实现了InvocationHandler,看一下关键的invoke方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
获取拦截器链,
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 从缓存中查询
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 缓存没有则创建
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice 会创建调用链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass) {
...
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 检查class是否匹配
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 检查method 是否匹配
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
}
}
可以看到,这里从Advisor获取到对应的MethodInterceptor数组,MethodInterceptor中包括了Advisor中定义的advice(通知)。
回到ReflectiveMethodInvocation.proceed,ReflectiveMethodInvocation,顾名思义,反射方法进行调用
public Object proceed() throws Throwable {
// 是否到拦截器链尾了
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取下一个拦截器,currentInterceptorIndex初始值是-1
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 是否为动态拦截器
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
...
}
else {
// 直接调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
注意,invoke会将ReflectiveMethodInvocation自身作为参数。
调用链以ExposeInvocationInterceptor开头,ExposeInvocationInterceptor只是简单的配置和恢复上下文
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
// 设置上下文
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation); // 恢复上下文
}
}
mi.proceed()
会调用到ReflectiveMethodInvocation.proceed(),会调用到下一个拦截器,这时进入AspectJAroundAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
throws Throwable {
// argBinding绑定参数
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
argBinding负责绑定参数,实际就是把JoinPoint作为第一个方法参数。
protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
...
int numBound = 0;
if (this.joinPointArgumentIndex != -1) {
adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
}
return adviceInvocationArgs;
}
AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs会调用到AdviceMethod(aspectJAdviceMethod),就是执行通知
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
在环绕通知中
@Around("...")
public Object methodAroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = joinPoint.proceed(joinPoint.getArgs());
return result;
}
由于第一个参数就是JoinPoint,所以joinPoint.proceed(joinPoint.getArgs());`就可以调用下一个拦截器,这样就实现了拦截器链调用
网友评论