前言
原来只是想看下Spring事务管理的原理,但在寻找事务起作用的源头时,就把Aop的代码几乎看遍了。。。所以就顺便写了一篇关于Aop原理的文章。希望能帮到大家(^_^)
SpringBoot自动配置
和看事务管理一样,还是根据SpringBoot配置了哪些关键类来分析原理。可以从Spring.factories找到Spring自动配置类AopAutoConfiguration
。该类根据配置文件有没有spring.aop.auto=true(该值默认为true)。该类上添加了@EnableAspectJAutoProxy
注解,所以我们可以很清楚的看出,springboot默认是开启aop功能的。而@EnableAspectJAutoProxy
向spring容器中添加了自定义配置Aop起作用的关键类AnnotationAwareAspectJAutoProxyCreator
Aop原理
代理类的创建
SpringBoot自动配置给容器加入了Aop的核心类,AnnotationAwareAspectJAutoProxyCreator
,该类实现了SmartInstantiationAwareBeanPostProcessor接口,所以在bean的创建前后分别会调用该类的postProcessBeforeInstantiation
和postProcessAfterInstantiation
方法。
postProcessBeforeInstantiation
方法会获取TargetSource来在对象创建前调用createProxy来创建代理对象。目前还没搞清楚什么情况会有TargetSource。 postProcessAfterInstantiation
方法调用wrapIfNecessary方法,先获取所有的切点拦截器,创建的时候与代理类所绑定。具体创建代理类的逻辑实在是没看懂,Spring自己封装了cglib代理类实现,不过也是创建了DynamicAdvisedInterceptor
为主拦截器的代理类,还有之前查找的所有切面拦截器。下面源码就是Spirng通过我们配置的切面表示创建Advisor的过程。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
//第一次去获取切面配置类
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// 获取所有类名 遍历
for (String beanName : beanNames) {
Class<?> beanType = this.beanFactory.getType(beanName);
// 如果该类有@Aspect注解,并且不是AspectJ类
//We need to detect this as "code-style" AspectJ aspects should not be interpreted by Spring AOP.
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);
//创建对方法进行增强处理的Advisor(InstantiationModelAwarePointcutAdvisorImpl)
//该增强器默认有AspectJExpressionPointcut作为你匹配,之后进行matches是会使用
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 {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
return advisors;
}
复制代码
DynamicAdvisedInterceptor
类是Aop每个代理类都有的拦截器,当调用代理类的方法时,首先会调用该类的intercept
方法。
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
// 对aop暴露进行处理,如果暴露则将代理类置入当前线程中,之后嵌套调用可以取到
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取原始对象(代理前对象)
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取拦截器链,就是在创建代理类前获取的拦截处理器,对方法进行匹配,和之前讲的事务Advisor一样
// 通过MethodMatcher来匹配,这边是AspectJExpressionPointcut的mathces对表达式进行解析
// 自定义的切面是通过之前的Advisor来生成的拦截器
// MethodBeforeAdviceAdapter AfterReturningAdviceAdapter ThrowsAdviceAdapter
//通过是否匹配上面三种adapter分别生成
//MethodBeforeAdviceInterceptor AfterReturningAdviceInterceptor ThrowsAdviceInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 没有增强处理器直接执行原始对象的方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
//调用CglibMethodInvocation.process(),
//该方法会递归执行所有拦截器链中的方法,知道调用完成原始方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 对返回结果进行处理
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
复制代码
其他Spring切面
@EnableAsync
可以开启Spring管理的线程池,利用注解方式简单实现方法多线程调用。但是有一点需要注意(我觉得是Spring的bug),该注解实现还是利用的Aop,但是使用另一个Bean后置处理器:AsyncAnnotationBeanPostProcessor
,从下面代码可以看出,在bean创建完成后会对未代理过的类创建代理对象,如果已经是代理类则添加一个切面处理器进去。由于在新创建代理类的时候使用的是独立的后置处理器,所以在切面设置的一些属性对@Async
无效(例如expose暴露)。所以如果想让只有@Async
注解的代理类,想要使暴露生效只能额外对该后置处理器添加属性。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
// 如果该bean已经被处理过(代理类)
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
// 如果需要被处理(有@Async注解)
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
// 如果需要被处理(有@Async注解)
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
复制代码
总结:
Spring通过为元类创建代理类添加DynamicAdvisedInterceptor
的拦截器来实现拦截器链,通过拦截器链我们自己创建的切面添加到拦截器链当中(可以自定义顺序),这样非常灵活方便的为我们提供了对类方法扩展的功能。另外推荐一篇对AOP扩展的文章,写的很好。觉得本文对你有帮助的小伙伴不妨点个赞,你们的关注是我继续下去的动力。