AOP 源码解读
其他博客参考:https://blog.csdn.net/l6108003/article/details/106577515/
SPI 读取 AopAutoConfiguration 配置类
在 spring-boot-autoconfigure-2.5.3.jar 中通过 SPI 读取自动配置类 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
使用时是否需要添加 @EnableAspectJAutoProxy ?
从配置类中可以看出,SpringBoot 默认已经开启了 AOP,故使用时,无需再添加 @EnableAspectJAutoProxy 注解。
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
@Bean
static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
return (beanFactory) -> {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
};
}
}
}
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy 导入了 @Import(AspectJAutoProxyRegistrar.class) 类。 Spring 在处理 @Import 注解时,就会实例化导入的这个类和执行到这个类的顶层父类 ImportBeanDefinitionRegistrar.registerBeanDefinitions() 方法。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
* true: 无论目标对象有没有实现接口,都是用 CGLIB 动态代理。
* false: 目标对象实现了接口,使用 JDK 动态代理;目标对象没有实现接口,则使用 CGLIB 动态代理。
* 注:JDK 动态代理必须目标对象实现接口。CGLIB 则没有这个要求。
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
* 该属性设置代理对象是否需要暴露,说白了就是是否需要把代理对象设置到 ThreadLocal 中。
* 要获取代理对象,就可以使用 AopContext.currentProxy()。
*/
boolean exposeProxy() default false;
}
AspectJAutoProxyRegistrar
这里主要是将 AnnotationAwareAspectJAutoProxyCreator 注册到 spring 中。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 这里将 AnnotationAwareAspectJAutoProxyCreator 注册到 spring 中
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);
}
}
}
}
AnnotationAwareAspectJAutoProxyCreator
AspectJAutoProxyRegistrar 类的继承关系如下:
├─AnnotationAwareAspectJAutoProxyCreator
│ ├─ extends AbstractAdvisorAutoProxyCreator
│ ├─ extends AbstractAutoProxyCreator
│ ├─extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
│ ├─SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
│ └─extends BeanPostProcessor
可以看出,它其实主要是一个 BeanPostProcessor 后置处理器类。 BeanPostProcessor 是在普通 Bean 之前实例化的,这就意味着,普通 Bean 在初始化的过程中会被各种 BeanPostProcessor 进行拦截。 最终在实例化 bean 之后,调用后置处理器的时候执行到 BeanPostProcessor.postProcessAfterInitialization() 方法,返回 AOP 代理对象。
AopConfigUtils
public abstract class AopConfigUtils {
/**
* The bean name of the internally managed auto-proxy creator.
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
/**
* Stores the auto proxy creator classes in escalation order.
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
// InfrastructureAdvisorAutoProxyCreator 用于处理以 @EnableTransactionManagement 注解形式开启事务。因为事务底层也是AOP实现的。
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
// AspectJAwareAdvisorAutoProxyCreator用于处理以 <aop:aspectj-autoproxy proxy-target-class="true"/> xml 配置形式开启AOP。
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
// AnnotationAwareAspectJAutoProxyCreator 用于处理以 @AspectJ 注解形式开启AOP。
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
// 省略其他代码
}
入口?在哪里调用的 AnnotationAwareAspectJAutoProxyCreator?
├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ ├─下面是依赖注入的核心方法(非常重要)
│ │ │ │ │ │ │ │ ├─populateBean(beanName, mbd, instanceWrapper);
│ │ │ │ │ │ │ │ ├─下面是依赖注入完成后的调用(非常重要)
│ │ │ │ │ │ │ │ ├─exposedObject = initializeBean(beanName, exposedObject, mbd);
│ │ │ │ │ │ │ │ │ ├─AOP 的入口方法。这里完成对 AnnotationAwareAspectJAutoProxyCreator(实际是一个 BeanPostProcessor) 的使用。
│ │ │ │ │ │ │ │ │ ├─wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
由于 AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 类,进而又实现了 BeanPostProcessor 接口, 那么这里就会执行到 BeanPostProcessor.postProcessAfterInitialization() 方法,返回 AOP 代理对象。
由于 AbstractAutoProxyCreator 类重写了 postProcessAfterInitialization() 方法,因此,最终会调到这里。
// 类中省略了其他方法的代码
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 这里创建了代理对象,并返回。最终这个对象会在 Spring 容器中
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
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;
}
// Create proxy if we have advice.
// 如果这个bean有advice的话,则创建当前bean的代理,重点看,重要程度5
// 得到所有的可用于拦截当前 bean 的 advisor、advice、interceptor
// 筛选查找有 advice 的 bean,并包装为 List<Advisor> 返回。
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//如果有切面,则生成该bean的代理,并把被代理对象bean实例封装到 SingletonTargetSource 对象中
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;
}
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
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 = new ProxyFactory();
// 把 AnnotationAwareAspectJAutoProxyCreator 中的某些属性copy到proxyFactory中
proxyFactory.copyFrom(this);
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 组装advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 把advisor加入到proxyFactory
proxyFactory.addAdvisors(advisors);
// 把targetSource对象加入到proxyFactory
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 获取代理对象
return proxyFactory.getProxy(classLoader);
}
}
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
找到合法的 Advice 类。
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
/**
* 查找 @Aspect 注解的类,核心方法
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到候选的切面,其实就是一个寻找有 @Aspect 注解的过程,把工程中所有有这个注解的类封装成Advisor返回
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对有@Order@Priority进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
}
如何查找当前 bean 的切面
- 从 Spring 中查找所有的切面
- 首先找到所有的 BeanDefinition 对象对应的 beanName,反射拿到对应的 Class 对象,判断该类上面是否有 @Aspect 注解,有则是我们要找的;
- 然后循环该 Class 里面的除了@PointCut 注解的方法,找到方法上的 Around.class,Before.class, After.class,AfterReturning.class,AfterThrowing.class 注解,并且把注解里面的信息,比如表达式、argNames、注解类型等信息封装成对象 AspectJAnnotation;
- 接着创建 pointCut 对象,把注解对象中的表达式设置到 pointCut 对象中;
- 最后就是创建 Advice 对象,根据不同的注解类型创建出不同的 Advice 对象,对象如下 :AspectJAroundAdvice,AspectJAfterAdvice, AspectJAfterThrowingAdvice,AspectJMethodBeforeAdvice, AspectJAfterReturningAdvice 最终把注解对应的 Advice 对象和 pointCut 对象封装成 Advisor 对象。
- 找到拦截当前 bean 的切面
- 从收集到的所有切面中,每一个切面都会有 pointCut 来进行模块匹配,其实这个过程就是一个匹配过程,看看 pointCut 表达式中的内容是否包含了当前 bean,如果包含了,那么这个 bean 就有切面,就会生成代理。 :::
小结
代理对象的创建过程整体来说并不复杂,首先找到所有带有@Aspect 注解的类,并获取其中没有@Pointcut 注解的方法,循环创建切面, 而创建切面需要切点和增强两个元素,其中切点可简单理解为我们写的表达式,增强则是根据@Before、@Around、@After 等注解创建的对应的 Advice 类。 切面创建好后则需要循环判断哪些切面能对当前的 Bean 实例的方法进行增强并排序,最后通过 ProxyFactory 创建代理对象。