Spring AOP切面原理
核心注解@EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
核心导入了AspectJAutoProxyRegistrar组件,进一步分析AspectJAutoProxyRegistrar组件
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//核心逻辑
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);
}
}
}
}
发现AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口
ImportBeanDefinitionRegistrar是Spring提供来用于自动装配的接口 核心方法有2个主要是传入扫描类的注解信息,Spring的BeanDefinitionRegistry 通过这个registry可以注册组件
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
明白了 BeanDefinitionRegistry 的作用进一步研究这个方法是AOP实现的核心AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
又调用了AOPConfigUtils的内部方法最终追踪到
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注册AnnotationAwareAspectJAutoProxyCreator bean定义信息
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 首先判断一下bean工厂里面有没有 AUTO_PROXY_CREATOR_BEAN_NAME这个bean 真实名称叫org.springframework.aop.config.internalAutoProxyCreator 第一次进来肯定没有
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
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;
}
// 开始创建bean
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;
}
- 判断工厂中是否已经存在org.springframework.aop.config.internalAutoProxyCreator这个bean定义信息
- 没有开始创建并注册调用 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
- beanDefinition 需要注册一个AnnotationAwareAspectJAutoProxyCreator的组件
- 进入DefaultListableBeanFactory#registerBeanDefinition方法 此处执行完毕之后bean工厂中已经加入了名称为org.springframework.aop.config.internalAutoProxyCreator且类型为AnnotationAwareAspectJAutoProxyCreator的BeanDefinition信息,用于等下Spring启动之后创建这个bean
现在需要重点研究AnnotationAwareAspectJAutoProxyCreator 这个类干了什么
查看AnnotationAwareAspectJAutoProxyCreator 的继承树
-
AnnotationAwareAspectJAutoProxyCreator 核心需要注册的类也是整个AOP原理的入口
-
BeanFactoryAware 接口是spring aware接口体系中的一个,实现了该接口的类Spring会把BeanFactory传递给该组件,拿到BeanFactory就可以使用BeanFactory进行组件的注册
-
SmartInstantiationAwareBeanPostProcessor 核心继承类,他又继承了InstantiationAwareBeanPostProcessor 该类中有2个核心方法
- postProcessBeforeInstantiation 在Spring创建bean之前能够通过这个方法返回一个代理对象来替代需要创建的bean,这次是Spring AOP代理对象的核心,如果此方法返回了对象,Spring会直接拿加强过的bean作为组件注册,不会再注册我们自己写的bean信息
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { @Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; } default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; } }
-
BeanPostProcessor bean的后置处理器 spring功能扩展的核心,在bean初始化前后可以对bean做一些增强 如@Autowire注解就有对应了AutowiredAnnotationBeanPostProcessor来进行对bean的属性赋值的增加
以上分析AnnotationAwareAspectJAutoProxyCreator 的主要功能,下面进入Spring自动注册流程的分析
查看主类的run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
- 获取SpringApplicationRunListener 并在合适的地方触发这些listener
- 在准备创建IOC环境之前 listener start方法
- 在准备ConfigurableEnviroment 之前调用listeners.environmentPrepared
- 准备环境
- 根据项目类型创建不同的上下文 如MVC上下文还是WEB-FLUX上下文
- 准备上下文之前 listeners.contextPrepared(context)
- 准备上下文
- 准备上下文之后 listeners.contextLoaded(context)
- 刷新上下文 refreshContext
- afterRefresh 方法
- listener.started
- 执行ApplicationRunner和 CommandRunner
核心refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
-
刷新准备
-
获取beanFactory
-
准备beanFactory
-
执行beanFactory的postProcessor
-
注册BeanPostProcessor AOP org.springframework.aop.config.internalAutoProxyCreator核心逻辑在此处体现 包括了动态道理底层
- 先注册带优先级和排序priorityOrderedPostProcessors
- 在注册带排序的orderedPostProcessors
- 最后注册普通的PostProccessorts
-
其中跟AOP相关的核心BeanPostProcessor的创建就在这里
-
调用底层beanfactory的getBean 方法 底层有调用了doGetBean -> getSingleton获取单实例的bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // Quick check for existing instance without full singleton lock Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) { // Consistent creation of early reference within full singleton lock singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }
-
底层先从Spring的一级缓存 singletonObjects 中找有没有这个bean,第一次获取肯定没有
-
然后判断从一级缓存拿到的bean是不是为空 并且正在创建 如果正在创建尝试从二级缓存中拿 (此处逻辑是Spring 处理循环依赖的核心)
- 如果二级缓存 singletonObjects 也没有,再判断是否是需要早起暴露的bean
- 如果是加锁从三级缓存singletonFactories 拿到objectFactory然后调用objectFactory的getObject 方法生成一个bean
- 然后 移动到二级缓存earlySingletonObjects 并将三级缓存singletonFactories 从删除这个引用
-
第一次创建AOP的beanPostProcessor其实没有走上面逻辑,getSingleton直接返回null
-
-
下面开始创建bean,创建之前先标记当前bean被创建了
if (!typeCheckOnly) { markBeanAsCreated(beanName); }
-
然后获取bean的定义信息
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args);
-
然后获取是否存在依赖其他bean 如果有遍历获取
String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } }
-
判断是否是需要创建单例的bean如果是调用createBean创建
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // 省略 try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. AOP的核心在于这里 Spring在bean创建之前调用BeanPostProcessor的postBeforeInstantiation方法让BeanPostProcessor尝试自己返回一个代理对象的bean 还不是自己去创建 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { // 如果代理对象返回了bean 直接返回 没有就继续调用doCreateBean方法进行创建 return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
-
其实在我们创建AOP的BeanPostProcessor中还没有任何BeanPostProcessor可以拦截我们创建代理对象.但是这里的逻辑是我们自定义切面的核心 我们自己的bean会在创建以前被AOP的beanPostProcessor通过pointCut逻辑进行拦截,进行对我们的bean进行加强,稍后详细分析
-
因为没有任何BeanPostProcessor 返回了代理对象的bean,继续进入doCreateBean
if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); }
-
createBeanInstance创建bean实例
- 进去判断是否需要自动注入到参的构造器
- 如果没有特殊处理走无参构造器
- return instantiateBean(beanName, mbd);
-
instantiateBean底层就调用了Spring的BeanUtils工具类调用反射创建无参构造器
-
执行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
-
属性赋值populateBean(beanName, mbd, instanceWrapper); 如果内部需要注入bean再调用getSingleton去创建如果没有创建
-
执行初始化方法 invokeInitMethods
-
执行BeanPostProcessor的后置处理器 postProcessAfterInitialization方法
-
将beanPostProccessor加入到beanfactory
-
此时org.springframework.aop.config.internalAutoProxyCreator已经注册到了容器中
@Aspect
@Component
public class AopPointCut {
@Pointcut("execution(public * com.corn.turorial.spring.aop.AopTestService.*(..))")
private void pointCut() {
}
@Before(value = "pointCut()")
public void before() {
System.out.println("前置通知...");
}
@Around(value = "pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("环绕前通知..");
Object returnData = null;
// returnData = point.proceed();
try {
returnData = point.proceed();
} catch (Throwable throwable) {
System.out.println("方法出现了异常!");
}
System.out.println("环绕后通知..");
return returnData;
}
@After(value = "pointCut()")
public void after() {
System.out.println("后置通知...");
}
@AfterReturning(value = "pointCut()")
public void afterReturning() {
System.out.println("返回通知...");
}
@AfterThrowing(value = "pointCut()")
public void afterThrowing() {
System.out.println("异常通知...");
}
}
@Component
public class AopTestService {
public void testAop() {
// int a = 1/0;
System.out.println(" invoke com.corn.turorial.spring.aop.AopTestService.testAop !");
}
}
-
然后我们在研究这个beanPostProcessor是如何增加我们的类
-
直接定位到refresh方法的finishBeanFactoryInitialization(beanFactory); 初始化剩下的bean
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { getBean(beanName); } } } for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
-
此时我们关心我们自己的bean 判断是不是抽象的 是不是单例 是不是懒加载 然后判断是不是一个以&开头的工厂bean我们不是走getBean逻辑
-
本质上跟我们直接创建beanPostProcessor类似
-
尝试从一级缓存singletonObjects中拿
-
没有判断是否是单例的 是的话调用getSingleton的重载方法 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
进入查看createBean 类似一样的步骤 最核心跟普通bean不一样是resolveBeforeInstantiation方法 此时会进入AOP的 beanPostProcessor返回一个加强的bean
-
判断是不是InstantiationAwareBeanPostProcessor
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; }
-
找到AOP增加的beanPostProcessor
-
进入postProcessBeforeInstantiation方法
- 判断当前bean是否在advisedBean中是否需要增强
- 判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean或者是否是切面
- 是否需要跳过
- 获取候选增强器 切面的增强通知方法 【List candidateAdvisors】
- 每个封装的通知方法增强器是 InstantiationModelAwarePointcutAdvisor
- 判断每个增强器是否是 AspectJPointcutAdvisor
-
进入postProcessAfterInitialization方法
- wrapIfNecessary(bean, beanName, cacheKey);//包装如果需要的情况下
- 获取当前bean的所有增强器 specificInterceptors
- 获取候选的所有增强器 (根据切入点获取需要切入方法)
- 获取bean能使用的增强器
- 增强器排序
- 保存当前bean的adviseBeans
- 如果当前bean需要增强,创建当前bean的代理对象
- 获取所有增强器
- 保存到proxyFactory中
- 创建代理对象 Spring 底层有两种代理模式JDK JdkDynamicAopProxy 和 CGLIB ObjenesisCglibAopProxy
- 给容器中返回当前组件使用cglib增强代理对象
- 以后容器中获取的就是这个组件的代理对象,执行目标方法,代理对象就会执行通知方法
目标方法执行
- 容器中保存了组件的代理对象,对象保存了详细信息(增强器,目标对象等)
- CglibAopProxy.intercept();拦截方法执行
- 根据ProxyFactory对象获取将要执行的目标方法拦截器
- List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 遍历所有增强器转换为Interceptor registry.getInterceptors(advisor);
- 将增强器转为List
- 如果没有拦截器直接执行目标方法
- 如果有拦截器 将目标对象和目标方法传入 CglibMethodInvocation对象 调用 并调用 Object retVal = mi.proceed();
- 拦截器链的触发过程
- 如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组大小-1相等(说明已经执行到了最后一个拦截器) 执行目标方法
- 链式获取每一个拦截器,执行拦截器的invoke方法,每个拦截器等待下一个拦截器执行完毕返回 递归调用,保证通知方法与目标方法的调用顺序
总结
- @EnableAspectJAutoProxy 开启AOP
- @EnableAspectJAutoProxy 向容器中注册一个组AnnotationAwareAspectJAutoProxyCreator
- AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
- 容器创建过程
- registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
- finishBeanFactoryInitialization 初始化剩下的单实例bean
- 创建业务逻辑和切面组件
- AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
- 组件创建完成之后,判断组件是否需要增强
- 是切面通知方法,包装成增强器Advisor给业务逻辑组件创建一个代理对象cglib
- 调用目标方法
- 代理对象执行目标方法
- CglibAopProxy.intercept();
- 得到目标方法的拦截器链 由增强器包装成拦截器MethodInterceptor
- 利用拦截器的链式机制,依次进入每个拦截器进行执行
- 正常执行 前置通知->目标方法->后置通知->返回通知
- 异常执行: 前置通知 -> 目标方法 -> 后置通知 -> 异常通知
-