Spring AOP實現
概念簡介
- Aspect:系統中,功能模塊或者類的橫切面的一種抽象。舉例來說,web應用常見的事務管理即是典型的Aspect。各個服務功能(或類方法),都需要實現事務管理(一般指數據庫事務),這種橫跨多個功能的相同邏輯,可以稱之為Aspect。
- Join Point:系統功能的執行點,方法調用或者方法拋出的異常處理,都可以稱之為Join Point。AOP的目的就是在方法某處執行自定義的功能,歸納為在【哪里】執行【什么功能】,這個【哪里】就是指Join Point。Spring中,Join Point指的是方法調用,從方法層級來切入。
- Advice:在Join Point執行的具體動作,即【什么功能】。Advice分為多種類型,around、before、after等。通常,Advice以攔截器Interceptor的方式實現,某個方法的Advice的interceptor會組成一個鏈,來執行多個Advice的功能。
- Pointcut:匹配Join Point的規則。例如,可以指定匹配帶有【add】前綴的所有方法。Advice要關聯Pointcut使用,來確定動作具體在哪里執行。Spring使用的是AspectJ的表達式。
- Introduction:通常意義上的Advice都是附加在某個已有的方法上來指定額外的功能,Introduction可以在指定類上增加方法或者屬性。通過Introduction可以幫指定bean引入新的接口,實現新的功能。
Spring代理實現技術
? Spring代理的實現方式有兩種:
JDK代理:如果代理目標類實現了至少一個接口,那么接口的方法代理就可以使用JDK代理來實現。如果目標類沒有實現任何接口,那么將使用CGLIB來實現代理功能
CGLIB:主要實現方式是對生成一個目標類的子類,來對方法實行覆蓋,所以不可覆蓋的方法無法利用此方式來代理。
? Spring內部依賴于這兩種方式來實現代理,下面簡單舉例,說明一下二者的實現方式的區別
JDK代理
? 由于JDK代理需要接口的實現,所以先自定義一個簡單的接口:
public interface Fly {
void fly();
}
? 定義一個簡單類實現接口:
public class Bird implements Fly{
@Override
public void fly() {
System.out.println("this is bird flying");
}
}
? JDK代理主要使用InvocationHandler
接口來實現方法的代理:
public class FlyInvocationHandler implements InvocationHandler {
/**
* 代理目標類
*/
private Object target;
public FlyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理方式執行前后,自定義邏輯
System.out.println("invocation interceptor, before");
Object invokeResult = method.invoke(target, args);
System.out.println("invocation interceptor, after");
return invokeResult;
}
/**
* 返回代理類對象
*
* @return the proxy
* @author liuxinxing5 2018年11月30日 11:05
*/
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
}
}
? 測試代理類:
public class JdkProxyTest {
public static void main(String[] args) {
FlyInvocationHandler handler = new FlyInvocationHandler(new Bird());
Fly fly = (Fly) handler.getProxy();
fly.fly();
}
}
? 測試輸出:
invocation interceptor, before
this is bird flying
invocation interceptor, after
CGLIB
public class EnhancerDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
// 設置代理目標
enhancer.setSuperclass(EnhancerDemo.class);
// 設置代理的action,即Advice
enhancer.setCallback(new MethodInterceptorImpl());
EnhancerDemo demo = (EnhancerDemo) enhancer.create();
demo.test(100);
}
public void test(int i) {
System.out.println("inside enhancer demo " + i);
}
private static class MethodInterceptorImpl implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("interceptor begin ");
Object res = methodProxy.invokeSuper(o, objects);
System.out.println("interceptor end ");
return res;
}
}
}
? 測試輸出:
interceptor begin
inside enhancer demo 100
interceptor end
Spring代理實現邏輯
簡單示例
? 首先先定義一個簡單的Bean:
public class TestBean {
// 被代理方法
public void test() {
System.out.println("inside test bean");
}
}
? test()
方法是被代理的測試方法,下面需要定義代理的配置。Spring代理配置可以使用兩種方式,XML配置和注解配置。
XML配置
? 新增一個aop的配置類,XMLAop.java
public class XMLAop {
// 用于before Advice測試
public void before() {
System.out.println("inside xml configured before method");
}
// 用于around Advice測試
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("inside xml configured around method 1");
Object result = point.proceed(point.getArgs());
System.out.println("inside xml configured around method 2");
return result;
}
}
? XML配置aop.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<!--XMLAop配置為Bean-->
<bean id="xmlAop" class="com.sscon.aop.spring.XMLAop"/>
<aop:config>
<!--Aspect配置-->
<aop:aspect id="xmlAspect" ref="xmlAop">
<!--定義pointcut匹配規則,用于匹配join point,這里直接匹配所有test方法-->
<aop:pointcut id="somePointCut"
expression="execution(* com.sscon.aop.spring.*.test(..))" />
<!--指定before的Advice action-->
<aop:around method="around" pointcut-ref="somePointCut" />
<!--指定around的Advice action-->
<aop:before method="before" pointcut-ref="somePointCut" />
</aop:aspect>
</aop:config>
<bean id="test" class="com.sscon.aop.spring.TestBean" />
? 測試test()
方法輸出:
public static void main(String[] args) {
ApplicationContext c = new ClassPathXmlApplicationContext("aop.xml");
// 獲取test bean
TestBean test = (TestBean)c.getBean("test");
// 指定test方法
test.test();
}
? 測試輸出:
inside xml configured around method 1
inside xml configured before method
inside test bean
inside xml configured around method 2
注解配置
? 注解配置方式就是對XMLAop
類作簡單修改,增加注解:
@Aspect
public class XMLAop {
@Pointcut("execution(* com.sscon.aop.spring.*.test(..))")
public void test() {
}
@Before("test()")
public void before() {
System.out.println("inside xml configured before method");
}
@Around("test()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("inside xml configured around method 1");
Object result = point.proceed();
System.out.println("inside xml configured around method 2");
return result;
}
}
? 關鍵注解:
@Aspect:表明此類是一個Aspect配置
@Pointcut:注解于
void
返回值的方法,用于定義join point的匹配規則@Before:定義before類型的Advice,方法內指定執行的邏輯
@Aroud:定義around類型的Advice,方法內指定執行的邏輯,注解的方法的參數第一個必須為
ProceedingJoinPoint
,使用ProceedingJoinPoint.proceed
方法類實現對被代理目標方法的調用...
? XML配置aop.xml
移除aspect的相關配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<!--XMLAop配置為Bean-->
<bean id="xmlAop" class="com.sscon.aop.spring.XMLAop"/>
<bean id="test" class="com.sscon.aop.spring.TestBean" />
? 測試test()
方法輸出:
inside xml configured around method 1
inside xml configured before method
inside test bean
inside xml configured around method 2
源碼分析
AOP功能入口,創建ProxyCreator
? Spring xml配置文件中,<aop:aspectj-autoproxy>
是開啟aop功能的入口,所以我們從此xml標簽的解析來分析Spring的處理流程。
? 在AopNamespaceHandler
類中,Spring注冊了aop標簽配置的解析器,AspectJAutoProxyBeanDefinitionParser
:
// AopNamespaceHandler.java
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 注冊處理aspectj-autoproxy標簽的處理器
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
? AspectJAutoProxyBeanDefinitionParser
類實現了BeanDefinitionParser
接口,BeanDefinitionParser
是Spring用來解析<beans>
直接子節點的接口,主要邏輯是parse
方法:
// AspectJAutoProxyBeanDefinitionParser.java
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.
registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
// AopNamespaceUtils.java
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注冊代理的creator
BeanDefinition beanDefinition = AopConfigUtils.
registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 處理proxy-target-class 和 expose-proxy屬性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
// AopConfigUtils.java
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(
AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
? 跟蹤到AopConfigUtils
的registerOrEscalateApcAsRequired
方法,可以看到Spring注冊代理creator的邏輯,其中參數cls
是AnnotationAwareAspectJAutoProxyCreator.class
,這個方法的主要邏輯是注冊一個創建代理的工具類:
如果當前沒有注冊AUTO_PROXY_CREATOR_BEAN_NAME的代理Creator,那么使用cls參數指定的類作為工具創建
如果當前注冊了AUTO_PROXY_CREATOR_BEAN_NAME的Creator,那么要進行優先級排序,確定具體使用AnnotationAwareAspectJAutoProxyCreator還是已經創建的Creator
Spring默認使用AnnotationAwareAspectJAutoProxyCreator
// AopConfigUtils.java
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果當前已注冊AUTO_PROXY_CREATOR_BEAN_NAME的creator,那么需要做一下選擇
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition =
registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 已注冊的creator和指定cls不同,根據優先級排序選擇
int currentPriority =
// 當前已注冊的creator的優先級,優先級根據APC_PRIORITY_LIST中的
// 序號來表示,AnnotationAwareAspectJAutoProxyCreator位于序號2
// 是最高的優先級
findPriorityForClass(apcDefinition.getBeanClassName());
// cls指定的creator的優先級
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 如果cls指定的優先級高,那么更換為cls的creator
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
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;
}
代理配置處理
? 注冊完代理的Creator后,還需要處理指定的配置信息,讀取用戶的配置信息后,保存:
// AopNamespaceUtils.java
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注冊代理的creator
BeanDefinition beanDefinition = AopConfigUtils.
registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 處理proxy-target-class 和 expose-proxy屬性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
// AopConfigUtils.java
private static void useClassProxyingIfNecessary(
BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
// PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class"
boolean proxyTargetClass = Boolean.parseBoolean(
sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// EXPOSE_PROXY_ATTRIBUTE = "expose-proxy"
boolean exposeProxy = Boolean.parseBoolean(
sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
// AopConfigUtils.java
public static void forceAutoProxyCreatorToUseClassProxying(
BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition =
registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
// AopConfigUtils.java
public static void forceAutoProxyCreatorToExposeProxy(
BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition =
registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
? proxy-target-class與expose-proxy屬性:
proxy-target-class:Spring默認使用JDK代理來實現代理功能(前提是類至少實現了一個接口),該屬性可以強制指定使用CGLIB來實現代理功能
expose-proxy:被代理對象如果存在自我調用,例如a方法調用b方法,兩個方法都被代理,那么b方法是無法執行代理邏輯的。
被代理對象內部方法調用的問題
? 拿一個簡單的例子來描述這個問題,TestBean
有方法被代理,test()
與test2()
,test內部調用test2,test2方法配置的代理邏輯不會執行:
public class TestBean {
// 被代理方法
public void test() {
System.out.println("inside test bean");
test2();
}
// 被代理方法
public void test2() {
System.out.println("inside test2 bean ");
}
}
? 如果代理的配置如下:
@Aspect
public class XMLAop {
// test test2方法都會匹配
@Pointcut("execution(* com.sscon.aop.spring.*.test*(..))")
public void test() {
}
@Before("test()")
public void before() {
System.out.println("inside xml configured before method");
}
}
? 輸出如下:
inside xml configured before method
inside test bean
inside test2 bean
? 如果希望test2()
方法也執行代理的邏輯,Spring給出一個解決辦法是,將expose-proxy
修改為true嗎,暴露Spring生成的代理實體,且修改test()
方法的邏輯:
public class TestBean {
public void test() {
System.out.println("inside test bean ");
// 拿到Spring生成的代理,指定test2()的方法,如果不修改expose-proxy配置,會報錯
((TestBean)AopContext.currentProxy()).test2();
}
public void test2() {
System.out.println("inside test2 bean ");
}
}
使用代理Creator創建代理
? Spring默認使用AnnotationAwareAspectJAutoProxyCreator
來對Spring管理的Bean做代理創建處理,此類實現了BeanPostProcessor
,BeanPostProcessor
的關鍵方法是postProcessAfterInitialization
。Bean初始化完成之后會調用此方法對Bean進行處理。該方法的實現在抽象父類AbstractAutoProxyCreator
:
// AbstractAutoProxyCreator.java
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;
}
? 從上面的邏輯可以看到,當沒有緩存時,使用wrapIfNecessary
方法進行代理初始化:
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判斷是否已經處理過
if (beanName != null && 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;
}
// 拿到Bean所有配置的interceptors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 根據interceptors創建代理并緩存
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;
}
獲取Bean所有配置的interceptors
? Spring內部使用Advisor
類來保存Advice和Pointcut的配置信息,獲取Bean所有可用的Advisor的基本邏輯是:
首先拿到所有的advice配置,保留xml配置與注解配置
根據被代理類的實體,決定具體哪些advice可以應用于當前實體類
對advice排序,返回
// AbstractAdvisorAutoProxyCreator.java
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()) {
// 多個advisor需要進行排序,確定所有代理的advice邏輯的執行順序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
? findCandidateAdvisors,主要負責讀取所有配置的Advice,包括兩個部分,一種是xml配置,一種的注解配置:
// AnnotationAwareAspectJAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
// 將父類讀取的advisor也保存到結果中,這里主要是xml配置的advice
List<Advisor> advisors = super.findCandidateAdvisors();
// 讀取注解配置的advice
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
? 查詢注解配置的advice信息的基本邏輯是:
首先獲取所有的Bean信息,遍歷
判斷Bean是否具有Aspect注解,如果有,獲取Advisor信息,其中包括配置的Pointcut規則,Advice配置等
緩存查詢結果,方便下次查詢
// BeanFactoryAspectJAdvisorsBuilder.java
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// 緩存結果
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
// 查詢所有的bean
String[] beanNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
// 是否合法,默認返回true
if (!isEligibleBean(beanName)) {
continue;
}
// 拿到Bean的Class對象
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 如果有Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind()
== PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(
this.beanFactory, beanName);
// 獲取所有的advice信息并保存到列表
List<Advisor> classAdvisors =
this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException(
"Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(
this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory
.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 從緩存中獲取advice信息并返回
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory =
this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
? 獲取Bean類的Advisor的邏輯:
遍歷Bean的方法,帶有@Pointcut注解的方法除外,因為@Pointcut配置的是join point的匹配規則,單獨處理
如果該方法有配置@Before等注解,那么構造Advisor,放入結果列表中
如果屬性有配置@DeclareParents,那么構造Advisor,放入結果列表中
// ReflectiveAspectJAdvisorFactory.java
public List<Advisor> getAdvisors(
MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory
.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory
.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
// 保存Advisor信息
List<Advisor> advisors = new LinkedList<Advisor>();
// 遍歷當前Bean類的非Pointcut注解的方法,判斷是否有@Before等注解配置
for (Method method : getAdvisorMethods(aspectClass)) {
// 嘗試獲取方法的Advisor,如果當前類沒有@Pointcut配置或者方法沒有任何Advice配置
// 都會直接返回null
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory,
advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
if (!advisors.isEmpty()
&& lazySingletonAspectInstanceFactory.
getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new
SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 構造@DeclareParents注解的Advisor,這個配置是附加在屬性上,所以單獨處理
// @DeclareParents主要是用于給Bean類增加新的方法,而不是在已有方法上附加行為
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
? 接著上述邏輯,獲取方法的Advisor的邏輯為:
// ReflectiveAspectJAdvisorFactory.java
public Advisor getAdvisor(Method candidateAdviceMethod,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 獲取Pointcut配置
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod,
aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 根據查詢到的注解初初始化Advisor
return new InstantiationModelAwarePointcutAdvisorImpl(
expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
private AspectJExpressionPointcut getPointcut(
Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 獲取@Before等注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory
.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(
candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
// AbstractAspectJAdvisorFactory.java
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class,
AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation =
findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
? 由查詢到的注解配置信息構造Advisor(包含Advice,Pointcut等信息):
// InstantiationModelAwarePointcutAdvisorImpl.java
public InstantiationModelAwarePointcutAdvisorImpl(
AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder, String aspectName) {
...
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
...
}
else {
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 根據@Before等初始化Advice
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(
this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
? 初始化Advice的邏輯,可以看到是根據不同的注解生成不同的Advice對象,主要由工廠生成:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
....
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation =
(AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
...
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
...
}
? 到此邏輯,Spring已經可以拿到用戶配置的所有Aspect,接下來是遍歷這些配置,過濾出哪些Aspect配置可以應用于當前Bean類
過濾可應用于Bean的interceptors
? 上一步查詢出已經配置的所有的Aspect的配置,Advisor列表,根據Advisor中的Pointcut配置,來比對Bean中的方法,如果可以匹配,那么Advisor可應用于當前Bean:
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// AopUtils.java
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) {
// @DeclareParents類型
if (candidate instanceof IntroductionAdvisor
&& canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// introduction類型已經處理
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
? 主要判斷邏輯處于canApply方法,主要邏輯是判斷Bean的所有接口與Bean自己的所有方法是否可以應用Advisor中的Pointcut規則,如果任一方法可以,那就可以認為Advisor可以用于當前Bean:
// AopUtils.java
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor)
.getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
return true;
}
}
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;
}
// Pointcut配置的方法過濾為默認True類型,直接返回即可
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher =
(IntroductionAwareMethodMatcher) methodMatcher;
}
// 存放代理目標類的所有接口類
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(
ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 把代理目標類也放入set
classes.add(targetClass);
// 上述所有類的任一方法可以匹配Pointcut,認為此Advisor可以應用于當前被代理類
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;
}
? 至此,Spring已經拿到當前Bean可應用的Advisor列表,接下來就是利用Advisor和Bean來創建代理類
代理創建邏輯
? 前文提到的AbstractAutoProxyCreator
的wrapIfNecessary
方法中包含了實際代理創建的邏輯:
// AbstractAutoProxyCreator.java
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
... proxyFactory的初始化邏輯
// 利用proxyFactory創建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
// ProxyFactory.java
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
// ProxyCreatorSupport.java
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
// DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
// 這里判斷使用哪一種代理創建方式
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// ObjenesisCglibAopProxy是CglibAopProxy子類,做了一些邏輯優化
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
? 可以看到,Spring根據代理目標類是否實現接口,配置中是否強制開啟CGLIB,來決定使用哪一種方式來創建代理。
JdkDynamicAopProxy
? JdkDynamicAopProxy與JDK代理簡單實例中的一致,實現了InvocationHandler接口,主要邏輯位于invoke方法中,主要是將所有interceptor組成一個鏈,然后調用鏈執行,最后執行被代理方法:
// JdkDynamicAopProxy.java
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
...
try {
Object retVal;
...
// interceptor組成一個鏈,鏈式調用
List<Object> chain = this.advised.
getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.
adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.
invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
...
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
return retVal;
}
finally {
...
}
}
? interceptor鏈執行:
// ReflectiveMethodInvocation.java
public Object proceed() throws Throwable {
// 最后執行join point方法,也就是被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers
.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice
instanceof InterceptorAndDynamicMethodMatcher) {
// 匹配當前方法,執行攔截的代理邏輯
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method,
this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 不匹配當前方法,跳過
return proceed();
}
}
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
CglibAopProxy
? CGLIB構造代理的方式與示例類似,都是利用Enhancer類來進行構造:
// CglibAopProxy.java
public Object getProxy(ClassLoader classLoader) {
try {
...
// 配置Enhancer...
Enhancer enhancer = createEnhancer();
...
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(
AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(
new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 獲取關鍵的代理執行邏輯方法,callback方法
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 設置CallBackFilter
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(),
this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 設置CallBack方法
return createProxyClassAndInstance(enhancer, callbacks);
}...
}
? 獲取CallBack方法的主要邏輯為:
// CglibAopProxy.java
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 獲取aop配置的CallBack
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// 一些優化策略
...
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // xml和注解配置的aop代理邏輯
targetInterceptor, // 優化
new SerializableNoOp(), // 優化
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// 一些優化策略
...
return callbacks;
}
? DynamicAdvisedInterceptor
實現了MethodInterceptor
接口,也就是CGLIB示例中的CallBack方法的實現:
// DynamicAdvisedInterceptor.java
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised
.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 直接調用目標類的方法
Object[] argsToUse = AopProxyUtils
.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 同樣是調用鏈的創建,CglibMethodInvocation直接繼承JDK代理使用的
// ReflectiveMethodInvocation,主要邏輯沒有變化
retVal = new CglibMethodInvocation(proxy, target,
method, args, targetClass,
chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
? 使用JDK或CGLIB創建代理后,Bean在AOP的Postprocess的流程就結束了。后續調用Bean方法時,就可以實現AOP方法的調用。