目录
@[toc]
前言
IOC/DI , AOP 是Spring最重要的两个特性 ,也是面试高频被问到的部分,前面我们已经分析了Spring的IOC相关源码以及DI依赖注入相关源码,从本篇文章开始我们着手分析Spring的AOP源码 。
开始之前,你需要对AOP 原理,JDK动态代理,CGLIB动态代理有一定的理解。这里先上一个图,后面源码分析的时候可以看着图来
AOP的理解
AOP基本概念
AOP是为面向切面编程,为什么要面向切面,何为切面?我们知道对于OOP面向对象而言在某些开发场景中是有一定不足,由于面向对象的思想是纵向的,它面对的是一个一个的对象,当我们需要在多个类中引入同一个公共的业务时(比如:事务,操作日志等),那么在每个类中都要引入公共的业务代码,从而造成代码大量重复,代码结构不优雅,不方便维护 ,这个时候就需要使用到面向切面的编程来解决这个问题。使用AOP可以把分散在多个类中的公共的代码剥离出来,和业务本身的代码解耦, 然后通过动态代理将公共业务代码作用到多个对象,代码结构也更加优雅。
所以可以认为 面向切面 是对 面向对象 的补充,它的思想是横向的,它面向的是一个切面,如果把一个对象看做一个点,那么多个对象就是一个面,是为切面,AOP多用于:事务,日志,监控,流控等等业务场景。
AOP实现原理
AOP的实现原理是基于动态代理,动态代理就是在运行时期动态的为某个类(原生类)生成代理类以达到代码增强的目的,且代理类是持有原生类的,可以在代理类中调用原生类以及做一些增强业务。
动态代理分为JDK动态代理和CGLIB代理,CGLIB代理需要导入相关的jar包。两者的区别是JDK动态代理要求原始类(被代理类)需要实现至少一个接口。而CGLIB则是基于继承进行代理,原生类可以不实现任何接口。
对于Spring而言默认采用JDK动态代理,如果原生类没有实现任何接口,Spring会选择CGLIB代理,或者你可以通过配置文件强制指定使用CGLIB代理。
AOP案例
下面我们使用AOP来做一个事务管理案例:在每个Service方法执行前后添加事务的代码
1.创建一个普通类,这个类的方法需要有事务
@Service
public class UserServiceImpl implements IUserService {
public void insert() {
System.out.println("UserServiceImpl.insert:保存User...");
}
public void delete() {
System.out.println("UserServiceImpl.delete:删除User");
}
}
2.创建一个切面类,这个类里面提供公共的业务代码,即:事务代码
@Component
@Aspect
public class TranscationManager {
//定义切点,表达式作用于所有到service的所有的方法
@Pointcut("execution(* cn.xxx.*.service.*.*(..))")
public void pointcut(){
}
//前置通知 , 方法执行前执行,用来开启事务
@Before("pointcut()")
public void begin(JoinPoint joinPoint){
System.out.println("TranscationManager.begin:开启事务...:");
}
//后置返回通知 ,方法正常返回后执行, 用来提交事务
@AfterReturning("pointcut()")
public void commit(){
System.out.println("TranscationManager.commit:提交事物...");
}
//异常通知,方法出现异常调用,用来回滚事务
@AfterThrowing(value = "pointcut()",throwing="e")
public void rollback(JoinPoint joinPoint,Throwable e){
System.out.println("TranscationManager.rollback:回滚事物咯...:"+e.getMessage());
}
//最终通知,不管方法会不会出现异常,都会执行,用来关闭资源
@After("pointcut()")
public void close(){
System.out.println("TranscationManager.close:关闭连接...");
}
//环绕通知,拦截原始类的类的方法,可以通过 joinPoint调用原始的类
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint){
return null;
}
}
3.配置Spring支持AOP注解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--开启IOC注解支持-->
<context:component-scan base-package="cn.xx" />
<!--开启AOP注解支持,默认使用jdk动态代理,如果指定 proxy-target-class=true 则实例CGLIB代理-->
<aop:aspectj-autoproxy />
</beans>
4.测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application_aop.xml")
public class AopTest {
@Autowired
private IUserService userService ;
@Test
public void testAop(){
userService.insert();
System.out.println("======================================");
userService.delete();
}
}
控制台效果
TranscationManager.begin:开启事务...:
UserServiceImpl.insert:保存User...
TranscationManager.commit:提交事物...TranscationManager.close:关闭连接...
TranscationManager.begin:开启事务...:
UserServiceImpl.delete:删除User...
TranscationManager.commit:提交事物...
TranscationManager.close:关闭连接...
这里我们看到了,使用AOP可以把公共的代码剥离出去和业务变身代码解耦,同时也方便扩展。
怎么理解这个AOP案例,首先要明白需求:在多个service方法执行前,否 或 出现异常做出相应的事务处理。我们把UserService看着原生类, 把TranscationManager 切面看着是增强代码,那么Spring是如何做到把 TranscationManager 的增强逻辑 加入到 UserService的方法前后的呢?
- 找到所有原生类(被代理类):我们在 TranscationManager中定义了一个切点:
@Pointcut("execution(* cn.xxx.*.service.*.*(..))")
:这切点定义了一个表达式,这个表达式的含义就是找到cn.xxx包下所有的service的所有方法,Spring就知道了需要拦截这些方法的执行。 - 找到了service的方法,如何在方法前,后做事情?我们在TranscationManager中定义了@Before("pointcut()") 前置通知,@AfterReturning("pointcut()")后置通知等,当我们调用userService的方法之前就会触发 Before 前置通知中的逻辑 ,方法执行完成就会触发 AfterReturning 后置通知的逻辑,异常通知和最终通知也是一个道理。
实现原理就是动态代理,其实Spring为所有切点切到的类都生成了代理类,也就是说在test类中注入的
@Autowired private IUserService userService ;
其实并不是我们写的那个UserService,而是基于UserService代理出来的一个代理类。代理类持有原生类,且代理类和原生类有相同的方法,所以你感觉你在调用UserService,其实在调用代理类。在代理类中的方法对原生类方法做了增强 ,而增强的逻辑就是 TranscationManager 中的逻辑,比如调用userService.insert 实则进入了代理类的insert方法,方法中先调用TranscationManager@Before 前置通知业务,然后调用原生类的insert,方法结尾调用TranscationManager@AfterReturning 后置通知,出现异常调用TranscationManager@AfterThrowing异常通知等等。这样是不是就达到了上面的增强效果了。
如果没有去研究过JDK动态代理和CGLIB代理可能你看起来比较晕,对于Spring切面的东西这里不做太多解释了,不是本篇主要内容,下面我就对于这个AOP案例做源码分析。
AOP解析器
在上面的案例中我们通过 配置来开启AOP支持,稍微动动脑袋能想到Spring一定会有一个类来处理该配置。 在Spring中有一个接口叫 NamespaceHandlerSupport ,它提供了Spring配置文件的namespace的解析支持。
其中有一个实现叫 AopNamespaceHandler , 它是针对于 <aop: 开头的namespace 解析支持,看一下这个类的源码
AOP解析器:AspectJAutoProxyBeanDefinitionParser
//aop命名空间的NamespaceHandler 。
//为<aop:config>标签提供一个BeanDefinitionParser 。 config标签可以包括嵌套的pointcut 、 advisor和aspect标签。
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.5+ XSDs
//<aop:config 解析器
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
//【主角在这里】注册针对于<aop:aspectj-autoproxy 的解析器 AspectJAutoProxyBeanDefinitionParser
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
到这里我们看到了针对于 <aop:aspectj-autoproxy
的解析器 AspectJAutoProxyBeanDefinitionParser
,它实现了BeanDefinitionParser,解析逻辑都在parse方法中,源码如下:
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
//Element就是 <aop:aspectj-autoproxy 元素的封装
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册一个 AspectJAnnotationAutoProxyCreator
//用于处理当前应用程序上下文中的所有 AspectJ 切面,以及 Spring Advisor。
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//处理子节点
extendBeanDefinition(element, parserContext);
return null;
}
...省略...
}
该方法的作用主要是注册了一个 AspectJAnnotationAutoProxyCreator
自动代理创建器,它的作用就是用来处理Aop。 AspectJAutoProxyBeanDefinitionParser 的 parse 方法是在IOC启动过程中,通过DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
委派 BeanDefinitionParserDelegate#parseCustomElement
去解析的。
注册AnnotationAwareAspectJAutoProxyCreator
parse方法中比较重要的就是 AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
, 它创建了一个 AnnotationAwareAspectJAutoProxyCreator
代理自动创建器 ,AOP的功能重要就是通过它来完成的,它可以根据 Point 解定义的切点来自动代理相匹配的 bean
,跟一下该方法源码:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//【重要】通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对 proxy-target-class 和 expose-proxy 属性处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件 把 beanDefinition 注册到ParserContext上下文中
registerComponentIfNecessary(beanDefinition, parserContext);
}
该方法做了三件事情
- 通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator ,该类是AspectJ 切面处理类
- 对 proxy-target-class 和 expose-proxy 属性处理 ,就是把BeanDefinition中的proxyTargetClass和exposeProxy属性设置为true
- 这次组件, 把AnnotationAwareAspectJAutoProxyCreator 的 beanDefinition 注册到ParserContext上下文中
我们继续跟踪注册AnnotationAwareAspectJAutoProxyCreator 的代码:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
//BeanDefinitionRegistry:bean的注册器
//cls:AnnotationAwareAspectJAutoProxyCreator的类型
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果容器中已经包含了 org.springframework.aop.config.internalAutoProxyCreator 自动代理创建者的BeanDefinition
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
//获取BeanDefinition
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//class比较
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
//如果已经有自动创建器了,按照优先级比较选择使用哪一个
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//如果容器中还没有注册自动创建器,就注册一个
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//通过BeanDefinitionRegistry注册一个 代理自动创建器
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
方法会判断容器中如果已经注册了 自动代理创建器,则按照优先级选择使用哪个,如果么有注册就使用BeanDefinitionRegistry注册一个。
处理proxy-target-class和ExposeProxy
proxy-target-class 的对于 属性的处理,该属性的作用是指定代理的方式为CGLIB。
//对 proxy-target-class 和 expose-proxy 属性处理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
//获取 <aop:aspectj-autoproxy proxy-target-class="" /> proxy-target-class 属性
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
//如果proxyTargetClass=true,则使用CGLIB代理
//definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
//把 definition 中的 proxyTargetClass设置为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//当exposeProxy为true时暴露代理对象,会把proxy动态代理对象设置到AopContext上下文中
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
//definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
//把 definition 中的 exposeProxy 设置为true
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
这里做了两个事情
- 根据配置: 将 definition 中的 proxyTargetClass设置为true ,生成代理将会使用CGLIB方式,否则默认使用JDK动态代理
根据配置: 将 definition 中的 exposeProxy设置为true ,目的是把创建的代理对象添加到AopContext上下文中,为什么要这麽做?如果有如下代码:
public class AServiceImpl implements AService{ @Transactional public void a(){ this.b(); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void b(){ } }
这里的 this 是原生类,并不是代理类,也就意味这b的
@Transactional(propagation = Propagation.REQUIRES_NEW)
事务增强代码是不会执行的,对于这个问题我们可以做如下处理- 修改配置:
this.b() 修改为:((AService)AopContext.currentProxy()).b(); 得到代理类执行b()方法
增强器
上面的一个大堆流程主要是创建了一个 AnnotationAwareAspectJAutoProxyCreator ,那么它是如何来处理AOP的呢?看一下它的继承体系
AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,当Spring实例化这个Bean时会在这个Bean的initMethod初始化之后调用postProcessAfterInitialization方法,Aop的实现就在这里开始。AbstractAutoProxyCreator#postProcessAfterInitialization源码如下:
```java- Create a proxy with the configured interceptors if the bean is
- identified as one to proxy by the subclass.
- @see #getAdvicesAndAdvisorsForBean
*/
//如果 bean 被子类标识为代理,则使用配置的拦截器创建一个代理。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
}//根据Bean的class和name,创建一个缓存的key , Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { //对适合代理的Bean进行封装 return wrapIfNecessary(bean, beanName, cacheKey); }
return bean;
}
//创建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已经处理过,就直接返回Bean
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//不需要增强
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//是基础设施类(比如 Pointcut.class,Aspect.class等基础类不需要代理),
// 或者是原始类不做代理,比如 beanName以 .ORIGINAL 结尾就会跳过代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//获取增强,即:获取到上面案例中的TranscationManager中的增强方法,封装成一个一个,InstantiationModelAwarePointcutAdvisorImpl,该类可以是对切面方法的封装
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));
//把代理的type放入proxyTypes
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//缓存的key放入advisedBeans
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
方法中先判断了Bean是否需要创建代理,比如当前bean是Aspect,pintcut等基础设施类就不需要代理,然后调用 getAdvicesAndAdvisorsForBean 获取到增强器 ,最后 调用createProxy方法创建代理对象。
## 获取增强器
获取增强器是在 `AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean`中完成的 ,我们来一步步跟踪一下它的获取流程
```java
//[第一步] 找到增强器
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//找打增强器,提取成Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
//[第二步] 找到所有增强器,以及找到bean适用的增强器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到所有增强方法
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//找到当前bean适用的增强方法
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
上面逻辑做了两件事情, 找到所有增强器,以及找到bean适用的增强器,查找所有增强器在 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors中完成的,源码如下:
@Override
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) {
//调用 aspectJAdvisorsBuilder.buildAspectJAdvisors 构建增强器
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
这里主要通过 aspectJAdvisorsBuilder 去查找增强器,然后添加到advisors集合中返回。
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<>();
aspectNames = new LinkedList<>();
//获取到spring中所有的beanNames
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
//循环BeanName 获取增强方法
if (!isEligibleBean(beanName)) {
//不合法的Bean跳过
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
//根据名字得到类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//是否是切面类,有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);
//查找增强方法,前置,后置,异常,最终通知
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;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<>();
//找到所有切面类
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;
}
上面方法会先得到切面类 aspectNames,然后根据切面类从 advisorsCache缓存中得到增强方法并返回。
解析切面中的增强方法
当然如果还没有切面和增强方法,就会先从容器中得到所有的BeanName循环得到class,通过判断是否有aspect注解来得到切面。得到切面后,通过this.advisorFactory.getAdvisors(factory)
提取切面中的增强方法,并缓存到advisorsCache map中。下面是 ReflectiveAspectJAdvisorFactory#getAdvisors 源码
@Override
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<>();
//使用反射工具, ReflectionUtils#doWithMethods 获取切面类的所有方法
for (Method method : getAdvisorMethods(aspectClass)) {
//提取增强方法 , 把 method 提出成 Advisor【重要】
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
上面业务中通过 getAdvisorMethods(aspectClass) 获取切面类所有的方法,底层通过ReflectionUtils#doWithMethods 反射实现。 然后调用 ReflectiveAspectJAdvisorFactory#getAdvisor 提取出切面中的增强器 Advisor(对增强方法的封装)。重点看一下 getAdvisor 源码
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
//验证
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//根据切点信息生成增强器
//把切面的增强方法提取成一个一个的 Advisor,
//由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
==============================================================================================
//获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//【第一步】找到方法上的注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//【第二步】得到注解表达式:如:pointcut()或者 @Pointcut(" execution(...)")
//封装到AspectJExpressionPointcut对象
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
===============================================================================================
//找到切面注解
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
//就是要找这些注解
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
//找到指定方法的注解,封装成AspectJAnnotation
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
在上面逻辑中,把切面的增强方法提取成一个一个的 Advisor,由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装 ,源码如下:
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//切入点
this.declaredPointcut = declaredPointcut;
//切面类的类型
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
//增强的方法名
this.methodName = aspectJAdviceMethod.getName();
//方法的参数
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
//
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
//实例化 增强器
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
上面构造方法是把增强方法相关的信息进行了赋值,最后调用了一个 instantiateAdvice 来对增强器进行初始化,不同的增强逻辑不同,比如Before,After 他们的增强前置是不同的,所以需要不同的增强器来完成不同的逻辑,见:instantiateAdvice 方法源码
创建增强器
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//切面类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//验证
validate(candidateAspectClass);
//找到增强方法的注解封装
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
//判断class是否是切面
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//不同的增强做出不同的处理,创建了不同的 Advice
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
//前置AspectJMethodBeforeAdvice
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
//最终通知
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
//后置通知
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
//异常通知
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
//环绕通知
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
//切点
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
//给增强器设置参数
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
这里根据不同的增强注解生成不同的增强器,比如 AtBefore 会对应 AspectJMethodBeforeAdvice ,比如 AtAfter 对应了 AspectJAfterAdvice。增强器中都提供了一个 invoke 来调用增强方法。如AspectJMethodBeforeAdvice
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
public AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
//调用增强方法,即调用@Before注解的前置通知方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
@Override
public boolean isBeforeAdvice() {
return true;
}
@Override
public boolean isAfterAdvice() {
return false;
}
}
增强器的调用
这里有个疑问,上面已经针对不同的注解生成了不同的增强器,那么这些增强器在什么时候调用呢?当然是在我们调用对象的方法的时候,触发前置,后置等增强。在Spring内部有一个 MethodBeforeAdviceInterceptor 拦截器,该拦截器会在创建Bean的代理的时候被创建,它的作用就是在方法调用前拦截,我们看一下源码:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
//前置增强器
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用方法前:调用前置增强器中的增强
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//调用方法
return mi.proceed();
}
}
对于后置增强没有Interceptor ,而是在拦截器链中直接调用 AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
//调用后置增强
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
其他的增强这里就不一一分析了 , 到这里我们基本上把增强器的解析流程分析完成了。
选择适用的增强器
在上面分析中已经找到了所有增强,但是不是所有增强器都适合,所以会过滤出适用的增强,主要实现在AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
,其实就是找到满足我们配置的 切入点 的增强器,具体的细节这里就进去分析了。
创建代理
上面流程走完,找到了适合当前Bean的增强器,然后就会为当前Bean创建代理了,通过AbstractAutoProxyCreator#createProxy 完成
代理创建器:AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//创建ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
//拷贝当前类的属性
proxyFactory.copyFrom(this);
//判断是基于接口的代理,就是判断 <aop:aspectj-autoproxy proxy-target-class="false" 属性
//默认fasle,即:走JDK动态代理
if (!proxyFactory.isProxyTargetClass()) {
//确定给定的 bean 是否应该用它的目标类而不是它的接口来代理。
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//找到被代理类的接口interface ,添加到到 proxyFactory 代理工厂中
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//给代理工厂加入增强器
proxyFactory.addAdvisors(advisors);
//设置被代理类
proxyFactory.setTargetSource(targetSource);
//定制代理,是个空方法,可以进行扩展
customizeProxyFactory(proxyFactory);
//当配置被冻结时,不能进行任何建议更改。
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//通过 ProxyFactory 创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
看得出这个方法在配置代理工厂,ProxyFactory,配置好之后通过代理工厂创建代理。方法做了如下事情
- 把当前类中的属性添加到工厂
- 把被代理的接口添加到工厂
- 把增强器添加到工厂
- 把要代理的原始类添加到工厂
- 创建代理
该方法中通过判断 proxy-target-class="false" 来决定采用JDK动态代理或者CGLIB代理,之前有分析过
- 如果被代理类有接口,Spring默认使用JDK动态代理
- 如果被代理类有接口,可以配置 proxy-target-class="true" 强制使用CGLIB代理
- 如果被代理类没有接口,只能选择CGLIB代理 ,因为JDK动态代理只是支持有有接口的类,CGLIB是为被代理类生成一个子类,复写其所有方法来达到增强,CGLIB代理需要引入CGLIB库
继续跟进 proxyFactory.getProxy 方法
public Object getProxy(@Nullable ClassLoader classLoader) {
//先创建一个JDKDynamicAopProxy , 然后创建代理类
return createAopProxy().getProxy(classLoader);
}
-----------------------------------------------------------------------------------------------
@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.");
}
//判断目标是否有接口,选择使用JdkDynamicAopProxy创建代理,否则使用CGLIB
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//使用ObjenesisCglibAopProxy创建代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
ProxyFactory#getProxy 首先会创建一个AopProxy 代理创建器,根据目标类是否有接口来选择使用JDK代理:JdkDynamicAopProxy 和CGLIB代理:ObjenesisCglibAopProxy。然后调用getProxy方法创建代理。
JDK动态代理:JDKDynamicAopProxy
JdkDynamicAopProxy 实现了 InvocationHandler,InvocationHandler是JDK动态代理最核心的一个类,代理对象的方法调用都会被委托到 invoke 方法中去执行,JdkDynamicAopProxy#getProxy 源码如下:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
//创建代理
@Override
public Object getProxy(@Nullable 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);
}
//...省略代码...
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法调用
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果是equals方法:目标类本身没有实现 equals(Object) 方法。
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
//如果是hashCode方法:目标类本身没有实现 hashCode() 方法。
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//调用Advised 接口或者其父接口中定义的方法
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
//目标类
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
//获取此方法的拦截器通知链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
//如果没有拦截器能应用到该方法,直接反射调用方法
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//创建 ReflectiveMethodInvocation 方法调用
// 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();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
invoke方法中首先获取方法的拦截器通知链,如果有就会创建 MethodInvocation来调用方法,应用通知,如果没有拦截器链就直接反射调用方法。
方法增强拦截器:advice的织入
拦截器通知链是通过getInterceptorsAndDynamicInterceptionAdvice得到的:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
}
-----------------------------------------------
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
//用来装拦截器
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
//注册一系列 AdvisorAdapter,用于将 Advisor 转化成 MethodInterceptor
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//把advisor转换成MethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//检查当前 advisor 的 pointcut 是否可以匹配当前方法
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
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
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
getInterceptorsAndDynamicInterceptionAdvice这个方法主要是把Advisor 转成 MethodInterceptor , 也就是说Advisor可以应用到连接点,也就是当代理对象方法被调用时就可以触发相应的 Advisor 通知了。
在AOP中为各种通知封装了不同的拦截器,在上面代码中出现一个注册器:GlobalAdvisorAdapterRegistry 其中委托AdvisorAdapterRegistry 来实现增强拦截器的注册,默认实现类是DefaultAdvisorAdapterRegistry 代码如下:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
* 创建一个注册器,用来注册各种适配器
*/
public DefaultAdvisorAdapterRegistry() {
//方法前置通知适配器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
//后置通知适配器
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
//异常通知适配器
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//把advice 通知 包裹成 Advisor 增强器
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
//获取增强的方法拦截器
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
//通知
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
//通过适配器把advisor转发成MethodInterceptor
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
//注册适配器
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
下面是 MethodBeforeAdviceAdapter的源码:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
//是否支持
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
//给定一个MethodBeforeAdvice 前置通知 ,返回一个MethodBeforeAdviceInterceptor 方法前置拦截
return new MethodBeforeAdviceInterceptor(advice);
}
}
MethodBeforeAdviceInterceptor 是针对于前置通知的拦截器,在拦截方法的执行之前,可用触发前置通知,源码如下:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
//方法前置通知增强
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//调用前置通知增强
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//调用目标方法
return mi.proceed();
}
}
下面是 AfterReturningAdviceAdapter 后置通知适配器源码:
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}
下面是 AfterReturningAdviceInterceptor后置通知拦截器
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//先调用目标方法
Object retVal = mi.proceed();
//再调用后置增强
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
下面是ThrowsAdviceInterceptor 异常通知拦截器:
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
private static final String AFTER_THROWING = "afterThrowing";
private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);
private final Object throwsAdvice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//执行目标方法
return mi.proceed();
}
catch (Throwable ex) {
//收集异常,获取异常增强方法
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
//调用异常增强
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}
private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
Object[] handlerArgs;
if (method.getParameterCount() == 1) {
handlerArgs = new Object[] {
ex };
}
else {
handlerArgs = new Object[] {
mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
}
try {
//调用异常增强
method.invoke(this.throwsAdvice, handlerArgs);
}
catch (InvocationTargetException targetEx) {
throw targetEx.getTargetException();
}
}
使用反射调用方法
上面分析了Advice通知的注入过程,以及前置,后置,异常通知拦截器代码分析,现在代码回到 JdkDynamicAopProxy #invoke方法中 , 得到方法的拦截器后,如果方法没有拦截器通知链,就直接反射调用方法,否则会创建 ReflectiveMethodInvocation来调用方法
//获取此方法的拦截器通知链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
//如果没有拦截器能应用到该方法,直接反射调用方法
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//创建 ReflectiveMethodInvocation 方法调用
// 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();
}
AopUtils.invokeJoinpointUsingReflection 源码如下:
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
//反射调用方法
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
通过 ReflectiveMethodInvocation 调用方法
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
//动态匹配参数,看拦截器是否可用执行
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
//匹配失败,跳过当前拦截器,执行下一个拦截器
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
总结
到这里AOP的源码分析就结束了,最后总结一下大致流程
- AopNamespaceHandler中注册了一个AOP解析器 AspectJAutoProxyBeanDefinitionParser
- AspectJAutoProxyBeanDefinitionParser创建了 代理自动创建器AnnotationAwareAspectJAutoProxyCreator
- AnnotationAwareAspectJAutoProxyCreator 负责解析AOP,和创建代理类
- AnnotationAwareAspectJAutoProxyCreator解析切面,找到所有的增强方法封装成增强器,并找到适合Bean的增强器
- 调用AbstractAutoProxyCreator创建代理,默认使用 JDKDynamicAopProxy JDK动态代理,如果 proxy-target-class=“true” 使用CglibAopProxy创建CGLIB代理。
- 对于前置,后置,异常等等通知都有对应的拦截器,当代理类被调用就会先走方法的拦截器进行增强逻辑的处理。
文章接收,喜欢就一键三连吧,你的肯定是我最大的动力。