我写这篇博客的底层逻辑是什么?顶层设计在哪?最终交付价值是什么?过程的抓手在哪里?如何保证结果的闭环?我比别人的亮点在哪里?优势在哪里?我的思考和沉淀在哪里?我有形成自己的方法论么?我这个博客换别人来发是否会一样?全篇是如何做到对齐拉通的?
一,回首AOP
AOP 是 OOP 的延续,是 Aspect Oriented Programming 的缩写,意思是面向切面编程。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP 可以说也是这种目标的一种实现。
现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP 就实现了把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。
二,图解AOP
1,开启AOP功能
@EnableAspectJAutoProxy
开启aop功能的注解
看他的源码:@Import(AspectJAutoProxyRegistrar.class)
向容器中注册AspectJAutoProxyRegistrar
查看 AspectJAutoProxyRegistrar
类,里面只有一个方法 registerBeanDefinitions()
这个方法里 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)
,底层实际上调用了registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null)
,他又调用了registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)
,向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator
。
查看AnnotationAwareAspectJAutoProxyCreator
类的继承关系
由这个类的继承关系图可以看到这个类实现了BeanPostProcessor
和BeanFactoryAware
接口,由此定位到aop的抓手.
2,容器刷新
spring
的ioc
容器刷新的时候执行一个方法refresh(),refresh()
里面有两个重要的方法。
refresh()
里面第一个重要的方法registerBeanPostProcessors(beanFactory)
,他调用了initBeanFactory()
,里面 new AnnotationAwareAspectJAutoProxyCreator
,而这个AnnotationAwareAspectJAutoProxyCreator
的父类是 InstantiationAwareBeanPostProcessor
。
也就是开启aop
配置时,注册的类AnnotationAwareAspectJAutoProxyCreator
实际上是在这里作为beanPostProcessor
加入到容器中的。
refresh()
里面第二个重要的方法 finishBeanFactoryInitialization(beanFactory)
,加载剩下所有的单实例bean,他底层会调用createBean(beanName, mbd, args)
去创建要加载的bean对象,首先会先去执行resolveBeforeInstantiation()
。
在这个resolveBeforeInstantiation()
方法里面执行了两个方法分别调用AnnotationAwareAspectJAutoProxyCreator
里面的两个方法,postProcessBeforeInstantiation(beanClass, beanName)
,postProcessAfterInitialization(result, beanName)
。
postProcessBeforeInstantiation(beanClass, beanName)
尝试去返回一个bean对象,如果他成功返回bean对象,执行postProcessAfterInitialization(result, beanName)
。
分析postProcessAfterInitialization(result, beanName)
的逻辑:wrapIfNecessary()
包装这个返回的bean,他是怎么进行包装的呢?
getAdvicesAndAdvisorsForBean()
获取bean相关的所有的切面。
advisedBeans.put(cacheKey, Boolean.TRUE)
将获取到的切面与bean关联起来缓存。
createProxy()
底层利用jdk或者cglib的动态代理创建代理对象。
这一切都是在doCreateBean()
真正创建对象的方法之前执行的。
3,目标方法的执行
在检测到目标方法执行之前,会先执行intercept()
拦截。
getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
获取到所有的拦截器。
new CglibMethodInvocation().proceed()
代理对象执行目标方法。
dm.interceptor.invoke(this)
增强器在方法执行前后增强。
@EnableAspectJAutoProxy 开启aop功能的注解
@Import(AspectJAutoProxyRegistrar.class) 向容器中注册AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar
registerBeanDefinitions()
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)
registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null)
registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source) 向容器中注册了一个 AnnotationAwareAspectJAutoProxyCreator
由这个类的继承关系图可以看到这个类实现了BeanPostProcessor和BeanFactoryAware接口,由此定位到aop的抓手,接下来看与这两个类相关的方法
创建对象的时候 AnnotationAwareAspectJAutoProxyCreator 在对象创建前执行
refresh()
registerBeanPostProcessors(beanFactory)
initBeanFactory()
new AnnotationAwareAspectJAutoProxyCreator --->InstantiationAwareBeanPostProcessor
finishBeanFactoryInitialization(beanFactory)
preInstantiateSingletons()
getBean(beanName)
doGetBean(name, null, null, false)
getSingleton()
createBean(beanName, mbd, args)
resolveBeforeInstantiation(beanName, mbdToUse)
applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)
postProcessBeforeInstantiation(beanClass, beanName)
advisedBeans.containsKey(cacheKey)
isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)
applyBeanPostProcessorsAfterInitialization(bean, beanName)
postProcessAfterInitialization(result, beanName)
wrapIfNecessary(bean, beanName, cacheKey)
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
advisedBeans.put(cacheKey, Boolean.TRUE)
createProxy()
getProxy(getProxyClassLoader())
createProxyClassAndInstance(enhancer, callbacks)
doCreateBean(beanName, mbdToUse, args)
目标方法的执行
intercept
getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
new CglibMethodInvocation().proceed()
dm.interceptor.invoke(this)