概念定義
Advice
定義: 幹什麼
PointCut
定義: 在哪幹
Advisor
定義:組裝Advice和PointCut,在哪裡幹什麼
AOP啟動過程
AopAutoConfiguration
從SpringBoot的aop自動配置開始入手
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false)
public static class CglibAutoProxyConfiguration {
}
}
複製程式碼
可以是使用**@EnableAspectJAutoProxy**來開啟aop自動代理
根據spring.aop.proxy-target-class屬性來覺得是否使用cglib生成代理
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//是否使用cglib方式生成代理,預設使用jdk代理方式
boolean proxyTargetClass() default false;
//TODO 暫時不知道啥用
boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
//通過引數傳入BeanDefinitionRegistry物件,自行註冊需要的BeanDefinition
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//註冊AutoProxyCreator到容器中
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//解析@EnableAspectJAutoProxy屬性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//使用cglib代理
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//TODO 不知道啥用
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
#org.springframework.aop.config.AopConfigUtils
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
//判斷容器中是否已經註冊AUTO_PROXY_CREATOR_BEAN_NAME
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
//沒啥用,不用看
...
return null;
}
//容器中沒有AUTO_PROXY_CREATOR_BEAN_NAME的定義,註冊到容器中
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到容器中
注意:org.springframework.aop.config.internalAutoProxyCreator只是BeanDefintion的名字而已,不是一個類名.其對應的真實類是org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
來看一下AbstractAutoProxyCreator全家福
從全家福中我們可以看到AutoProxyCreator實現類大致分為兩種:
- 基於AOP標準概念(Advice,PointCut)
- 基於名稱匹配
從上面的全家福中可以看到以上3個都是屬於第一種的,為何AopConfigUtils只提供了這3中AutoProxyCreator的註冊? TODO暫時給不出解釋
代理建立過程
猜測:代理物件的建立時機應該是在例項化完成之後找到匹配的切面,然後組裝成一個代理物件
基於這種猜測我們在AbstractAutoProxyCreator中找到對BeanPostProcessor.postProcessAfterInitialization()的實現
AbstractAutoProxyCreator是個抽象類,並實現了幾個Spring生命週期方法(模板方法模式)
#AbstractAutoProxyCreator
//物件例項化完成之後呼叫
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
//快取
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//建立代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//抽象,匹配切面
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;
}
複製程式碼
過程總結:
-
得到匹配的Advice
切面匹配過程,下面會詳細講
-
織入Advice,生成代理
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //是否使用cglib生成代理 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } //新增Advisor Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } //建立代理 return proxyFactory.getProxy(getProxyClassLoader()); } protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { //公共Interceptor Advisor[] commonInterceptors = resolveInterceptorNames(); //commonInterceptors+specificInterceptors List<Object> allInterceptors = new ArrayList<Object>(); ... Advisor[] advisors = new Advisor[allInterceptors.size()]; ... return advisors; } #org.springframework.aop.framework.ProxyFactory public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } #org.springframework.aop.framework.ProxyCreatorSupport protected final synchronized AopProxy createAopProxy() { ... return getAopProxyFactory().createAopProxy(this); } #org.springframework.aop.framework.DefaultAopProxyFactory public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //是否使用cglib進行代理 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //cglib代理 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } 複製程式碼
具體的Proxy物件生成過程我們暫且不看
以上則是AbstractAutoProxyCreator建立代理的過程
下面我們分別來看基於AOP標準和基於名稱匹配的兩大陣營是如何獲取切面的
切面匹配過程
基於AOP標準
#org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//抽象,獲取可能匹配的Advice
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//抽象,獲取合格的Advice
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//對Advice進行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
複製程式碼
基於Advisor介面
#org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
#org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper
public List<Advisor> findAdvisorBeans() {
//返回所有Advisor介面的實現類
String[] advisorNames = null;
...
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
...
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
...
advisors.add(this.beanFactory.getBean(name, Advisor.class));
...
}
return advisors;
}
複製程式碼
基於AspectJ註解
#org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
@Override
protected List<Advisor> findCandidateAdvisors() {
//獲取基於Advisor介面的實現類
List<Advisor> advisors = super.findCandidateAdvisors();
//另加入基於AspectJ註解的Advisor(通過介面卡模式包裝成一個Advisor)
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
#org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
//1.從工廠中獲取所有帶有@Aspect註解的實現類
//2.解析其中所有方法上的註解
//3.通過介面卡模式包裝成Advisor返回
//過程不過多分析
....
return advisors;
}
複製程式碼
基於名稱匹配
#org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
//如果匹配則返回
if(){
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
//名稱不匹配則返回DO_NOT_PROXY標誌位 ,不進行代理
return DO_NOT_PROXY;
}
複製程式碼
BeanNameAutoProxyCreator只能對所有註冊的BeanName適用相同的Interceptor