aop涉及的核心类如下:
以上所有类都是aop包下的类。并且AbstractAutoProxyCreator实现了接口SmartInstantiationAwareBeanPostProcessor及其父类InstantiationAwareBeanPostProcessor、BeanPostProcessor并且实现了这仨接口的所有方法。
- BeanNameAutoProxyCreator:基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器。
- DefaultAdvisorAutoProxyCreator:基于Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中。
- AbstractAdvisorAutoProxyCreator:基于Bean中AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例。
AspectJAwareAdvisorAutoProxyCreator它用于xml配置版的AspectJ切面自动代理创建(aop:config)。
AnnotationAwareAspectJAutoProxyCreator用于基于注解的自动代理创建(aop:aspectj-autoproxy 或 @EnableAspectJAutoProxy)。
跟事务相关的AbstractAutoProxyCreator之InfrastructureAdvisorAutoProxyCreator:利用ImportBeanDefinitionRegistrar接口的子类AutoProxyRegistrar实现的。AutoProxyRegistrar是通过@EnableTransactionManagement之TransactionManagementConfigurationSelector间接实现的。在TransactionAutoConfiguration
类中开始初始化的。
跟AspectJ切面相关的AnnotationAwareAspectJAutoProxyCreator:利用ImportBeanDefinitionRegistrar接口的子类AspectJAutoProxyRegistrar实现的。AspectJAutoProxyRegistrar是通过@EnableAspectJAutoProxy实现的。在AopAutoConfiguration
类中开始初始化。
1、注解EnableAspectJAutoProxy
该注解「spring-context包下」已经被自动装配类AopAutoConfiguration
取代「spring-boot-autoconfigure包下」。
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
// spring.aop.proxy-target-class=false 并且被代理类实现了接口,则启动JDK代理。其余均是cglib代理。
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
该注解的主要作用是注册bean~AnnotationAwareAspectJAutoProxyCreator
:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
通过模板模式:AnnotationAwareAspectJAutoProxyCreatord 的父类AbstractAutoProxyCreator
实现了 BeanPostProcessor 接口的方法。也是实现代理的重要类。
2、切面类之IOC容器
IOC容器中涉及的切面类以及其通过属性Autowired注解引入的依赖都不会生成代理类。切点标识的切入类会以代理方式生成bean。
切入类的代理并非 IOC中步骤#4.3生成方式
2.1、AspectJAwareAdvisorAutoProxyCreator后置处理器
涉及文章中步骤4.1.1后置处理器。最终会调用到抽象类AbstractAutoProxyCreator#postProcessBeforeInstantiation
。
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)) {
// 在Spring实例化切面类的过程中,当前切面类beanClass在集合中持有
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);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
对于普通bean
以及切点标识的切入类
最终都会返回null。切面类会添加到集合advisedBeans
中。
2.2、AnnotationAwareAspectJAutoProxyCreator后置处理器
文章步骤#4.5.1中触发该后置处理器的postProcessAfterInitialization方法。最终都会调用到抽象类AbstractAutoProxyCreator#postProcessAfterInitialization
。
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;
}
// 判断是否是基础类:是否实现接口Advice、Pointcut、Advisor、AopInfrastructureBean等接口「Advice.class.isAssignableFrom(beanClass)」
// AspectJAwareAdvisorAutoProxyCreator#shouldSkip:处理切面中通知advisors
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 切点标识的切入类则会选择代理方式返回代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
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;
}
普通bean
添加到集合advisedBeans中后直接返回。- 切面类因为步骤2.1也会直接返回。
- 切点标识的切入类则会选择代理方式返回代理对象。
3、初始化全部候选通知Advice
候选通知包含Before、After、AfterReturning、AfterThrowing、Around等。
通过步骤#2中postProcessBeforeInstantiation、postProcessAfterInitialization均涉及候选通知Advice
的初始化。
通过AspectJAwareAdvisorAutoProxyCreator
#shouldSkip#findCandidateAdvisors 处理切面中的通知(advisors)。
3.1、预加载候选通知Advice信息
在服务启动过程中初始化IOC容器bean之前,候选通知Advice信息就可能初始化于缓存advisorsCache中。
public List<Advisor> buildAspectJAdvisors() {
// 切面名:@Aspect注解的类名
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {// 提前将切面涉及的各类通知缓存处理(事务|AOP)
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// aop功能中在这里传入的是Object.class类型,代表从容器中获取到所有组件的名称,然后一一遍历。如果容器中组件过多则遍历过程非常耗时。所以使用缓存处理切面信息,提高性能。
//事务功能是直接从容器中获取advisor.class类型的,相对Object.class类型选择范围很小,而且不耗能,所以针对事务的切面信息没有选择缓存处理。
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {//服务中所有bean name
...
// 判断当前类是否存在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);
// 解析切面类:ReflectiveAspectJAdvisorFactory#getAdvice
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 {
...
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#getAdvice:针对切面每个通知都会生成一个实例一一对应。
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
...
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {//获取切面类所有方法
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
...
return advisors;
}
InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
...
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
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;
}
....
return springAdvice;
}
3.2、AspectJAwareAdvisorAutoProxyCreator后置处理器
该后置处理器是spring默认初始化的后置处理器,所以在初始化IOC容器中bean的时候都会触发postProcessAfterInitialization、postProcessBeforeInstantiation。
在步骤#2中所有bean初始化过程中只要当前类不是切面类,均会执行shouldSkip
方法。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 如果存在候选通知Advisor是AspectJ相关的通知,则直接跳过
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
AspectJ与Spring中aop存在差别。
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 以下是涉及事务方面的通知(Advisors)
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 以下是涉及 aop 切面的通知(Advisors)
if (this.aspectJAdvisorsBuilder != null) {
//直接从advisorsCache缓存中获取全部的候选通知Advice
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
通过#3.1得到,所有候选通知Advice都已经初始化于缓存advisorsCache
之中。
4、切入类动态代理
DefaultAopProxyFactory#createAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//ObjenesisCglibAopProxy extends CglibAopProxy implements AopProxy
return new ObjenesisCglibAopProxy(config);
}
else {
// JdkDynamicAopProxy implements AopProxy
return new JdkDynamicAopProxy(config);
}
}
getProxy
- JdkDynamicAopProxy
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
}
- ObjenesisCglibAopProxy
门面模式:
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);//切面中切点指定的类(被代理类)。非切面类
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);// cglib中涉及的callback
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// ObjenesisCglibAopProxy#createProxyClassAndInstance
return createProxyClassAndInstance(enhancer, callbacks);
}
...
}
5、织入过程源码分析
Cglib
CglibAopProxy 中静态内部类 DynamicAdvisedInterceptor
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
TargetSource targetSource = this.advised.getTargetSource();//被代理类
...
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 将aop中自定义切面中每个通知转化为对应拦截器
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
}
}
JDK
JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;//被代理类
Object target = null;
try {
...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//获取到切面中全部通知
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 责任链模式调用通知
retVal = invocation.proceed();
}
...
return retVal;
}
...
}
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) {
...
}
else {
// this 表示当前类 ReflectiveMethodInvocation
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
interceptorsAndDynamicMethodMatchers:
- AspectJAfterThrowingAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
- AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
- AspectJAfterAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
- 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);
}
- MethodBeforeAdviceInterceptor
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 调用切面类中的before通知
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
isInfrastructureClass方法
protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
通过判断是否存在注解@Aspect
识别当前是否为切面类。
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
return retVal;
}
只要当前类是Advice、Pointcut、Advisor、AopInfrastructureBean类中其中一个都可以认定为是切面类。【是否意味着切面类也可以通过继承来实现呢?】