首先回顧:java
JDK動態代理與CGLIB動態代理spring
Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別數組
咱們得知 JDK動態代理兩要素:Proxy+InvocationHandler CGLB動態代理兩要素:Enhancer + MethodInterceptor(Callback)緩存
springAOP底層是經過動態代理和CGLB代理實現的。也就是spring最終的落腳點還應該是在Proxy+InvocationHandler 或者Enhancer + MethodInterceptor上。springboot
帶着這個期待咱們看看spring是如何組織AOP的,並在動態代理之上創建一個AOP體系的。bash
總結爲:從全部鏈接點中選出部分鏈接點, 進行攔截,執行額外操做。框架
AOP最先由AOP聯盟的組織提出的,制定了一套規範.Spring將AOP思想引入到框架中,必須遵照AOP聯盟的規範.ide
注意:各類組件很是之多. 我只把自認爲涉及到主線理解的組件列出工具
通知(加強器): 不要糾結於太多. 就統一理解爲攔截器或者加強器。post
注意一點:這裏的MethodInterceptor區別於上文提到的
org.springframework.cglib.proxy.MethodInterceptor不要混了。
複製代碼
鏈接點(被攔截):spring大多都是對方法調用的攔截, 這裏能夠理解爲方法調用.
1.Pointcut:定義哪些鏈接點能夠插入切面。提供ClassFilter 與MethodMatcher兩種匹配器,匹配鏈接點。
2.Advisor : 包裝Advice和Pointcut .語義: 在哪裏攔截, 插入什麼樣的加強器(在哪裏作什麼)Advisor=Advice+Pointcut 分爲
3.TargetSource: 對目標對象的封裝。
4.Advised接口 : 包裝 Advisor 與 TargetSource。 實現類AdvisedSupport:從其兩個屬性上,真切看出其封裝了 Advisor 與 TargetSource
5.AopProxy:AOP代理對象
JdkDynamicAopProxy與CglibAopProxy都實現了AopProxy的getProxy()方法,用於返回真正的代理對象。
6.AopProxyFactory:AOP代理策略工廠類。根據條件選擇使用JDK仍是Cglib的方式來建立代理對象。
7.ProxyCreatorSupport: 從其語義上理解,對建立代理對象的支持。咱們從其繼承關係上看看他是如何提供支持的。
8.AbstractAutoProxyCreator: 從其繼承關係。咱們分析下這個組件。
關於BeanPostProcessor與InstantiationAwareBeanPostProcessor的理解,仍是深入理解Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別。
小結:
若是總結下組件之間的關係:
開發人員定義切面信息--》spring解析出Advice,切點等配置信息--》AopProxyFactory根據配置建立代理對象--》代理方法執行。
這也是springAOP大部分工做內容。
籠統來看:
下面咱們重點看看定義的解析與代理的建立。
代理的執行過程: 咱們仍是以springboot環境下的AOP實現來說講AOP的過程.
首先配置AOP環境
@EnableAspectJAutoProxy註解上的@Import(AspectJAutoProxyRegistrar.class)引入AspectJAutoProxyRegistrar類.AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口. 因此其registerBeanDefinitions()會有一些注入BeanDefiniiton的操做 . registerBeanDefinitions()方法會向倉庫中注入一個AnnotationAwareAspectJAutoProxyCreator.
@Override
public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注入AnnotationAwareAspectJAutoProxyCreator擴展器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
複製代碼
AnnotationAwareAspectJAutoProxyCreator 間接繼承了AOP擴展工具AbstractAutoProxyCreator, 是一個BeanPostProcessor。
AbstractAutoProxyCreator:
這樣:AOP環境有了。
createBean()生產線在建立Bean的過程當中. 會執行全部的BeanPostProcessor. AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator)做爲一個BeanPostProcessor也在此時執行.
在Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別 講過. 實現了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor的會有5個方法伴隨Bean建立過程且執行順序。 postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessPropertyValues-->postProcessBeforeInitialization()-->postProcessAfterInitialization()
過程:
(2.1)首先執行的是postProcessBeforeInstantiation 實例化前置處理方法
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !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;
}
}
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
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;
}
複製代碼
主要分爲兩部分: (2.1.1)先判斷是否應該代理
重點看看shouldSkip()
/* 1.首先查找適於當前Bean的Advisor .通findCandidateAdvisors()去查找 findCandidateAdvisors()會通過兩個渠道獲取Advisors. > BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():是從倉庫中找實現了Advisor類的Advisor > BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()會從倉庫中取出@Aspect註解的切面類,解析出Advisor 重點說一下其中buildAspectJAdvisors >遍歷BeanFactory倉庫中的BeanDefinition,根據其類型判斷其是不是isAspect(): 判斷條件是類是否被@Aspect註釋,而且沒有被aspectj編譯過 >若是是, 根據當前BeanDefinition建立一個(AspectJAdvisorFactory)BeanFactoryAspectInstanceFactory工廠對象. >使用AspectJAdvisorFactory 工廠建立List<Advisor> >上文已經說過Advisor=Advice+Pointcut, Advice 就是對通知的封裝(@Before...), Pointcut 是對切點的封裝. 小結:此次知道咱們定義一個切面類, 被解析什麼樣子了吧 2.判斷找到的CandidateAdvisors中有沒有當前BeanDefinition,有的話就跳過。 */
@Override
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) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
複製代碼
(2.1.2) 判斷是否有自定義的 TargetSource。 若是有自定義TargetSource ,將當前beanName放入targetSourcedBeans緩存中,直接走建立代理的分支,不會走createBean去建立Bean,這裏就是給一個機會。 關於自定義TargetSource這個分支暫時不講。
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
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;
}
}
複製代碼
總結postProcessBeforeInstantiation工做內容:
(2.2)postProcessAfterInstantiation
(2.3)postProcessBeforeInitialization
(2.4)postProcessAfterInitialization() (敲黑板,重點)
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
複製代碼
關鍵便在於wrapIfNecessary方法: 名字 wrap if Necessary 若是知足條件就包裝 這個方法就能夠拆成兩部分看:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//1.自定義TargetSource,已經進行過代理子類生成 。 不包裝直接返回Bean實例
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//2.已經斷定不須要代理的, 不代理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//3.isInfrastructureClass(bean.getClass())是基礎設施類的不代理
//4.shouldSkip(bean.getClass(), beanName)應該跳過的不代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
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;
}
//5.沒有具體攔截器的不代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
複製代碼
咱們挨個分析下這兩部分
(2.4.1) 知足條件
不代理的狀況:
代理的的狀況:
Advisor尋找:重點就落在了此處。
即getAdvicesAndAdvisorsForBean方法,這裏進行的即是去容器中尋找適用於當前bean的Advisor,最終調用的是
AbstractAdvisorAutoProxyCreator.findEligibleAdvisors:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
複製代碼
findCandidateAdvisors: 獲取全部Advisor ,前面已經說過。 由於作了緩存此處直接從緩存中取。
findAdvisorsThatCanApply: 看其傳入的參數,candidateAdvisors(全部的候選Advisor), 也就是這個方法確定就是從全部的候選Advisor找出適合當前Bean
extendAdvisors: 容許子類添加advisor
適用性判斷 findAdvisorsThatCanApply最終調用AopUtils.findAdvisorsThatCanApply:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
//第一遍
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
//第一遍
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
複製代碼
此方法有兩個for循環。 第一個for循環尋找IntroductionAdvisor(引介加強)類型的advisor,調用AopUtils.canApply 第二遍for循環尋找普通的advisor,調用AopUtils.canApply
AopUtils.canApply針對兩種類型的Advisor作了不一樣的判斷:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//是否配置任意方法
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//逐一排查
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
複製代碼
到此,AopUtils.canApply返回true後。findAdvisorsThatCanApply()算是找到了能應用於當前類的Advisors. 再extendAdvisors後;對,應用於當前類的Advisors一番排序後,getAdvicesAndAdvisorsForBean工做完成。
getAdvicesAndAdvisorsForBean()返回若是不爲Null。那下面就是包裝。
(2.4.2) 包裝 在getAdvicesAndAdvisorsForBean返回advisors不爲null後,能夠建立代理。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
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());
}
複製代碼
咱們能夠看出,這裏兩大部分:
(1)建立proxyFactory工廠,並配置工廠
(2)proxyFactory.getProxy(getProxyClassLoader())返回代理對象。
proxyFactory.getProxy(ClassLoader classLoader)
proxyFactory.getProxy(ClassLoader classLoader) 首先會先建立一個默認的策略工廠DefaultAopProxyFactory。DefaultAopProxyFactory 會根據proxyFactory是基於接口的代理仍是基於類的代理,選擇建立JdkDynamicAopProxy對象,或者建立一個CglibAopProxy對象
這裏有必要介紹下DefaultAopProxyFactory.createAopProxy方法,此方法用來判斷是JDK代理,仍是CGLB代理。
if (config.isOptimize() //是否對代理類的生成使用策略優化
|| config.isProxyTargetClass() //設置proxy-target-class="true
|| hasNoUserSuppliedProxyInterfaces(config)) {//目標類是否有接口存在 且只有一個接口的時候接口類型不是
//SpringProxy類型
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//判斷目標類是不是接口 若是目標類是接口的話,則仍是使用JDK的方式生成代理對象
//若是目標類是Proxy類型 則仍是使用JDK的方式生成代理對象
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//CGLB代理。
return new ObjenesisCglibAopProxy(config);
}
else {
//JDK代理
return new JdkDynamicAopProxy(config);
}
複製代碼
咱們能夠看出高版本的會根據設置和目標類的實際狀況選擇使用CGLB或者JDK代理。也就是說,設置了
proxy-target-class="true"
不必定就是使用CGLB,而是根據實際狀況定。具體版本具體對待。
JdkDynamicAopProxy.getProxy()或者CglibAopProxygetProxy()纔是真正返回代理對象。
JdkDynamicAopProxy.getProxy()
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
複製代碼
咱們看到JDK動態代理的兩個要素: Proxy+InvocationHandler InvocationHandler 此時就是JdkDynamicAopProxy,同時JdkDynamicAopProxy封裝了advised。這樣完美的把advised與JDK動態代理聯繫在了一塊兒。
接下來就是在內存中生成一個字節碼JDK代理類$Proxy66.class,生成真正的代理對象了。
CglibAopProxygetProxy() (省略部分源碼,直奔主題)
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
Callback[] callbacks = getCallbacks(rootClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
return createProxyClassAndInstance(enhancer, callbacks);
}
複製代碼
咱們看到了Cglb熟悉的要素Enhancer 。MethodInterceptor去哪了呢?
跟進getCallbacks()方法,會發現此方法會建立一個DynamicAdvisedInterceptor。DynamicAdvisedInterceptor實現了MethodInterceptor,並封裝了advisors。
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
複製代碼
這樣,CGLB動態代理完美的與advised結合在了一塊兒。 接下來就是在內存中生成一個新的字節碼CGLB代理類***$$FastClassByCGLIB$$29e52466
,並生成真實代理對象了。
springaop 底層仍是JDK動態代理,CGLB動態代理。經過把加強器封裝到Advised中,把Advised與InvocationHandler或者MethodInterceptor聯繫起來,完美的實現AOP技術。
都說事務是根據AOP實現的,趁熱打鐵,看看事務是如何建立代理的?敬請期待 歡迎你們關注個人公衆號【源碼行動】,最新我的理解及時奉送。