上一篇看了Spring IOC源码,猿猿们都知道,有IOC就有AOP,那这篇就结合例子来看一下AOP的源码。
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
即对哪些方法进行切入,对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
把原来糅杂在业务逻辑代码中的非业务代码抽取出来,把功能相同的放在一个类中形成一个切面。类是对物体特征的抽象,切面就是对横切关注点的抽象。
需要切入的点、被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
对连接点进行拦截的定义。
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五种。
代理的目标对象。
将切面应用到目标对象并导致代理对象创建的过程。
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
基本概念网上有很多,就不细说了。这里要提一下AOP是一种思想,它的实现主要有Spring AOP和AspectJ,Spring实现AOP的底层相当复杂,所以借助了AspectJ的语法来实现,即使用了@Aspect注解来实现。
Spring AOP是在运行期进行织入的,而AspectJ是在编译期进行织入。
配置类
@Configuration
@ComponentScan(value = "com.ambition")
/**
* Spring AOP 默认使用 JDK 动态代理
*
* proxyTargetClass = true 时则代理目标对象时强制使用 CGLIB 代理
* @see DefaultAopProxyFactory#createAopProxy(org.springframework.aop.framework.AdvisedSupport)
*
* exposeProxy = true 暴露代理对象,这样就可以使用 AopContext.currentProxy() 方法获取当前代理的对象
* @see AopContext#currentProxy
* @see JdkDynamicAopProxy#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*
* 可以解决在方法里面调方法,或者用 this 关键字调方法,而无法被代理的情况
**/
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AopConfig {
}
切面类
@Aspect
@Component
public class AmbitionAop {
@Pointcut("execution(* com.ambition.service.CalculateImpl.*(..))")
public void pointCut() { }
@Before(value = "pointCut()")
public void methodBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【" + methodName + "】之前执行<前置通知>, 入参" + Arrays.asList(joinPoint.getArgs()));
}
@After(value = "pointCut()")
public void methodAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【" + methodName + "】之前执行<后置通知>, 入参" + Arrays.asList(joinPoint.getArgs()));
}
@AfterReturning(value = "pointCut()")
public void methodReturning(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【" + methodName + "】之前执行<返回通知>, 入参" + Arrays.asList(joinPoint.getArgs()));
}
@AfterThrowing(value = "pointCut()")
public void methodAfterThrowing(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行目标方法【" + methodName + "】之前执行<异常通知>, 入参" + Arrays.asList(joinPoint.getArgs()));
}
}
目标对象
@Component
public class CalculateImpl implements Calculate {
@Override
public int add(int numA, int numB) {
// System.out.println(1 / 0);
return numA + numB;
}
@Override
public int reduce(int numA, int numB) {
return numA - numB;
}
@Override
public int div(int numA, int numB) {
return numA / numB;
}
@Override
public int multi(int numA, int numB) {
return numA * numB;
}
}
测试类
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class);
Calculate calculate = context.getBean(Calculate.class);
int result = calculate.add(1, 2);
System.out.println("运算结果:" + result);
}
先来看一下它是如何被Spring IOC容器初始化并生成代理对象的,顺便说一下上一篇没有具体说明的部分,再说它的执行过程。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
可以看到这个注解上面导入了一个AspectJAutoProxyRegistrar类,它实现了ImportBeanDefinitionRegistrar,解析IOC源码的时候,我们看到Spring会将这种类型的组件放到一个集合中,然后统一调用registerBeanDefinitions()
方法,委托其进行BeanDefinition的注册。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 注册 AspectJ 相关的处理组件
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
可以看到主要代码就是AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary()
方法。
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls,
BeanDefinitionRegistry registry,
@Nullable Object source) {
// 容器中已经包含 "org.springframework.aop.config.internalAutoProxyCreator"
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 获取 BeanDefinition
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
/**
* 封装 AnnotationAwareAspectJAutoProxyCreator 为 RootBeanDefinition
*
* 名称为{@link AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME}
**/
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置顺序值
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册到容器中
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
这里Spring容器已经解析到刚刚导入的类了,然后会调用上面那个方法进行注册。
其实就是往Spring容器中注册一个AnnotationAwareAspectJAutoProxyCreator组件,很多EnableXXX注解都是这样将需要的组件注册到IOC容器,然后委托初始化过程来实现功能的扩展。
protected Object createBean(String beanName,
RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
......
try {
/**
* Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
* 给 BeanPostProcessors 一个返回代理而不是目标 Bean 实例的机会【重要】
* 但此时还没有创建代理对象,此时没有对象,只有 BeanDefinition
*
* 第一次调用后置处理器【跟 AOP 有关】
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*
* InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
* Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
*
* 此时对象还没有实例化,只有 BeanDefinition
* 无法进行代理,只是将切面找出来进行缓存
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
/**
* 实例化 Bean
**/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
然后来看看Spring是怎么将代理对象创建出来的,之前说resolveBeforeInstantiation()
方法将切面找出来进行缓存,那么是怎么缓存的呢,方法跟进去看一下。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这里第一次调用InstantiationAwareBeanPostProcessor类型的后置处理器的postProcessBeforeInstantiation()
方法,第二次调用BeanPostProcessor类型的后置处理器的postProcessAfterInitialization()
方法,一般只会调用第一个方法。
从上面的类体系结构图中可以看到,AbstractAutoProxyCreator是InstantiationAwareBeanPostProcessor的子类,所以会调用它重写的postProcessBeforeInstantiation()
方法。
先说一下AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,而它又实现了BeanFactoryAware,IOC容器在初始化过程中会回调setBeanFactory()
方法,AbstractAdvisorAutoProxyCreator有一个BeanFactoryAdvisorRetrievalHelper属性,在Spring回调的时候,会实例化为BeanFactoryAdvisorRetrievalHelperAdapter,它继承了BeanFactoryAdvisorRetrievalHelper,这个类在后面会有很大用处。
AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,它在Spring回调的时候,实例化了一个ReflectiveAspectJAdvisorFactory类,它继承了AbstractAspectJAdvisorFactory,它又实现了AspectJAdvisorFactory,和另一个BeanFactoryAspectJAdvisorsBuilderAdapter类,
它继承了BeanFactoryAspectJAdvisorsBuilder。
不用委托Spring注入,回调的时候进行实例化,Get了一项新技能,就是费头发。
看图更清晰一点:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 已经被代理过则返回
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 不应代理 或者 应该跳过
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 获取所有合格的增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建 AOP 代理
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
// 存入缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
这里shouldSkip()
方法就是缓存切面通知的地方。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 查找所有候选的通知
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
/**
* 是 AspectJPointcutAdvisor 的子类 并且 切面名称是 beanName
*
* 一般是 InstantiationModelAwarePointcutAdvisorImpl
**/
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
protected List<Advisor> findCandidateAdvisors() {
// 之前回调的时候实例化的 BeanFactoryAdvisorRetrievalHelperAdapter
this.advisorRetrievalHelper.findAdvisorBeans();
}
主要的方法就是findCandidateAdvisors()
方法,查找所有候选的通知。这里会先走父类的查找方法,再走子类的查找方法,主要是子类的方法。
protected List<Advisor> findCandidateAdvisors() {
/**
* 添加根据超类规则找到的所有 Spring Advisors
*
* 查找要在自动代理中使用的所有候选 Advisor【找 Spring AOP 的 Advisor】
**/
List<Advisor> advisors = super.findCandidateAdvisors();
/**
* 构建 BeanFactory 中所有 AspectJ 方面的 Advisors
**/
if (this.aspectJAdvisorsBuilder != null) {
/**
* 查找带有 AspectJ 注解的 Aspect bean【不同的注解对应不同的切面类】【找 AspectJ 的 Advisor】
*
* aspectJAdvisorsBuilder 是之前回调的时候实例化的 BeanFactoryAspectJAdvisorsBuilderAdapter
**/
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
用之前Spring回调时初始化的BeanFactoryAspectJAdvisorsBuilderAdapter组件来构建 AspectJ 的通知。代码如下:
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<>();
aspectNames = new ArrayList<>();
// 获取容器中所有组件的 beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
// 不合格则跳过
if (!isEligibleBean(beanName)) {
continue;
}
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 是切面【具有 @Aspect 注解并且不是由 ajc 编译】
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// AspectJ支持的不同子句(切面实例化模型)是单例的
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
/**
* 获取 AspectJ 注解对应的切面增强处理类
**/
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// 是单例则存入 Map> 缓存
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
// 否则存入 Map 缓存
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException();
}
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 ArrayList<>();
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;
}
主要方法就是ReflectiveAspectJAdvisorFactory的getAdvisors()
方法。代码如下:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取切面类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取切面类名称
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校验
validate(aspectClass);
/**
* 用装饰器包装 MetadataAwareAspectInstanceFactory,使其仅实例化一次
**/
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 遍历所有的除标注 @Pointcut 注解的通知方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 获取对应的增强器
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
......
return advisors;
}
getAdvisor()
方法获取对应的增强器,代码如下:
public Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect,
String aspectName) {
// 校验
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取切点表达式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 获取对应的增强器【重要】
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
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()) {
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 实例化对相应的增强器
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
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);
}
这里调用的是ReflectiveAspectJAdvisorFactory的getAdvice()
方法,主要就是由切面注解实例化不同的通知类。
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;
}
......
AbstractAspectJAdvice springAdvice;
// 由注解类型实例化不同的增强器
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
// @Around
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @Before
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @After
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// @AfterReturning
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
// @AfterThrowing
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException();
}
// 配置属性
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
// 绑定参数
springAdvice.calculateArgumentBindings();
return springAdvice;
}
这个方法执行完,可以看到将带有切面注解的方法都转换为对应的通知方法了。
那么前期的准备工作就执行完了,创建工作从AbstractAutowireCapableBeanFactory的initializeBean()
开始。
protected Object initializeBean(final String beanName,
final Object bean,
@Nullable RootBeanDefinition mbd) {
// 回调 Aware 及其实现类的方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
},
getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
/**
* 关键字:执行
* 执行 BeanPostProcessor 直接实现类的 postProcessBeforeInitialization() 方法
*
* @PostConstruct 注解是在这里面进行处理的
*/
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
/**
* 执行 Bean 生命周期回调中的 init 方法
*
* 实现 InitializingBean 接口并重写 afterPropertiesSet() 方法是在这里面进行处理的
*/
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
/**
* 关键字:改变
* 执行 BeanPostProcessor 直接实现类的 postProcessAfterInitialization() 方法
*
* 产生 AOP 代理,事务的代理等
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
applyBeanPostProcessorsAfterInitialization()
方法跟进去,发现其调用了BeanPostProcessor类型的后置处理器的postProcessAfterInitialization()
方法,这里就会进到AbstractAutoProxyCreator的postProcessAfterInitialization()
方法。
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;
}
主要代码就是wrapIfNecessary()
方法了,跟进去:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 没有代理过
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 是不应代理的基础结构类 或者 需要跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/**
* 获取所有合格的增强器
*
* 通过注解方式和 XML【】 方式配置的增强器
**/
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()
方法,有一部分代码跟之前的一样,主要多了查找可以应用于指定Bean的增强器这一过程,就不细说了,主要说createProxy()
创建代理对象方法:
protected Object createProxy(Class<?> beanClass,
@Nullable String beanName,
@Nullable Object[] specificInterceptors,
TargetSource targetSource) {
// beanFactory【DefaultListableBeanFactory】 是 ConfigurableListableBeanFactory 的子类
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
/**
* 暴露目标对象
*
* 设置 originalTargetClass 属性值为 beanClass
**/
AutoProxyUtils.exposeTargetClass(
(ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass
);
}
// 代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
/**
* proxyTargetClass 属性值是否为 False,默认为 False
**/
if (!proxyFactory.isProxyTargetClass()) {
/**
* 确定是否应使用给定的 Bean 替代其目标类而不是其接口
*
* preserveTargetClass 属性值为 True
**/
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
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);
}
// 获取代理对象【重要】
return proxyFactory.getProxy(getProxyClassLoader());
}
跟进去,最后执行的是DefaultAopProxyFactory的createAopProxy
方法:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 需要优化【默认为False】 或者 proxyTargetClass属性值为True【默认为False】 或者 没有用户提供的代理接口
if (config.isOptimize() || config.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(config)) {
// 目标类
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException();
}
// 是接口 或者 是代理的类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// 使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 代理
return new ObjenesisCglibAopProxy(config);
}
// 默认使用 JDK 动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
这里实例化代理对象的时候,传了一个AdvisedSupport参数,后面调用的时候转换为拦截器会用到它的方法。
传入后置处理器逻辑执行完之后,就可以看到创建的代理对象被织入了切面信息,感觉就像一个寻宝的过程,猿猿的生活就是这么朴实无华且枯燥。
因为目标对象是一个JDK代理对象,所以执行目标方法会被上面实例化的JdkDynamicAopProxy代理对象的invoke()
方法拦截:
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 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 目标对象没有自己实现 equals 方法
return equals(args[0]);
}
// 代理接口没有定义 hashCode 方法 且 调用的是目标对象的 hashCode 方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象没有自己实现 hashCode 方法
return hashCode();
}
// 声明类型是 DecoratingProxy
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 透明 且 声明类型是个接口 且 声明类型是 Advised
else if (!this.advised.opaque && method.getDeclaringClass().isInterface()
&& method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
/**
* 如果设置了 exposeProxy = true 则将代理对象设置到线程本地变量中
*
* @see org.springframework.context.annotation.EnableAspectJAutoProxy#exposeProxy()
**/
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
/**
* 获取此方法的拦截链
**/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
/**
* 检查是否有其他通知
* 如果没有,可以依靠目标直接反射调用,并避免创建 MethodInvocation
**/
if (chain.isEmpty()) {
/**
* 我们可以跳过创建 MethodInvocation 的操作:仅直接调用目标
* 请注意,最终的调用者必须是 InvokerInterceptor
**/
// 使给定参数适应给定方法中的目标签名
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 通过反射调用给定目标
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
/**
* 创建一个 ReflectiveMethodInvocation
**/
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
/**
* 通过拦截器链进入连接点【责任链模式】
**/
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class
&& returnType.isInstance(proxy)
&& !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException();
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
现在我们已经将通知织入到目标方法中去了,但是是如何执行这些通知方法的呢,getInterceptorsAndDynamicInterceptionAdvice()
方法看一下:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method,
@Nullable Class<?> targetClass) {
// 目标对象方法的缓存键
// public abstract int com.ambition.service.Calculate.add(int,int)
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;
}
Spring的设计思路很多操作都是先去缓存中获取,获取不到再进行复杂耗时的逻辑解析,然后放入缓存中,下次就直接获取到了,优化了性能,敲黑板。
AdvisedSupport类有一个AdvisorChainFactory属性,实例化了DefaultAdvisorChainFactory,由它进行逻辑解析。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config,
Method method,
@Nullable Class<?> targetClass) {
// 获取 DefaultAdvisorAdapterRegistry 实例
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取通知
Advisor[] advisors = config.getAdvisors();
// 拦截器集合
List<Object> interceptorList = new ArrayList<>(advisors.length);
// 目标类
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// 是 PointcutAdvisor 切点通知类型,DefaultPointcutAdvisor 和 InstantiationModelAwarePointcutAdvisorImpl 都符合条件
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 代理配置以预先过【默认为False】 或者 切面与目标类匹配
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 获取 TrueMethodMatcher 或 AspectJExpressionPointcut 方法匹配器
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// TrueMethodMatcher 不是 IntroductionAwareMethodMatcher 的子类,AspectJExpressionPointcut 是
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
// 匹配
if (match) {
// 转换为拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
// 封装为 InterceptorAndDynamicMethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 是 IntroductionAdvisor 类型
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;
}
主要功能就是将通知类转换为拦截器类,执行完后可以看到AspectJAfterReturningAdvice转换为了AfterReturningAdviceInterceptor,AspectJMethodBeforeAdvice转换为了MethodBeforeAdviceInterceptor,AspectJAfterAdvice、AspectJAroundAdvice和AspectJAfterThrowingAdvice本身就是拦截器。
如果没有拦截器,则直接反射调用目标方法。有的话则封装为ReflectiveMethodInvocation对象,调用它的proceed()
方法进行拦截处理。
public Object proceed() throws Throwable {
/**
* 从索引 -1 开始并提前增加【通过递归调用】
* 确保所有的责任者都完成处理逻辑
**/
// 是最后一个拦截器
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 直接通过反射调用目标方法
return invokeJoinpoint();
}
/**
* 获取下一个责任者
*
* ExposeInvocationInterceptor
* AspectJAfterThrowingAdvice
* AfterReturningAdviceInterceptor
* AspectJAfterAdvice
* AspectJAroundAdvice
* MethodBeforeAdviceInterceptor
**/
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
/**
* 是 InterceptorAndDynamicMethodMatcher 类型
* 这里都不是这个类型
**/
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
/**
* 动态匹配失败,跳过此拦截器并调用链中的下一个拦截器
**/
return proceed();
}
}
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这里的设计使用了一个currentInterceptorIndex
从 -1 开始的索引下标,通过递归调用,如果是最后一个拦截器,则直接反射调用目标方法,如果不是,则获取下一个拦截器,很巧妙,给大佬Orz了。
最后看一下各个拦截器的调用方法。
ExposeInvocationInterceptor的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
// 返回
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
主要是用ThreadLocal将当前MethodInterceptor进行暴露。
AspectJAfterThrowingAdvice的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 返回
return mi.proceed();
}
catch (Throwable ex) {
// 抛异常则调用
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
这个拦截器主要是处理异常的,有异常就做事,没有异常就什么也不干。之后的调用处理抛了异常,都会被这里捕获。
AfterReturningAdviceInterceptor的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 如果发生异常,则返回通知不执行,返回到异常通知逻辑,被捕获
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
AspectJAfterAdvice的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 返回
return mi.proceed();
}
finally {
// 返回通知一定会执行是因为放在 finally 块中
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AspectJAroundAdvice的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
// ReflectiveMethodInvocation 是 ProxyMethodInvocation
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(@Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue,
@Nullable Throwable ex) throws Throwable {
// 用给定的参数调用通知方法
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
protected Object invokeAdviceMethod(JoinPoint jp,
@Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue,
@Nullable Throwable t) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
// 处理调用参数
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// 使给定的方法可访问,并在必要时明确将其设置为可访问
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
/**
* 反射调用增强处理方法
*
* @see AopUtils#invokeJoinpointUsingReflection(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
**/
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException();
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
MethodBeforeAdviceInterceptor的invoke()
方法:
public Object invoke(MethodInvocation mi) throws Throwable {
// 前置通知逻辑
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 返回
return mi.proceed();
}
这就是为什么在没有环绕通知的情况下,没有异常的执行顺序是先执行前置通知,再执行后置通知,最后执行返回通知。
有异常的情况下,先执行前置通知,再执行后置通知,最后执行异常通知。
并且后置通知只要有就一定会执行。