Spring AOP原始碼實現分步解析
1 概述
1.1 示例
最基本的使用,在建立了業務介面和實現類後,通過配置<aop:config>....</aop:config>
標籤來指定<aop:pointcut
和<aop:advisor
。示例如下:
1.1.1 建立介面及實現類
介面:
public interface MockService {
public String hello(String s);
}
複製程式碼
實現類:
public class MockServiceImpl implements MockService {
@Override
public String hello (String s) {
System.out.println("execute hello");
return s;
}
}
複製程式碼
1.1.2 實現方法攔截
實現介面org.aopalliance.intercept.MethodInterceptor
public class CustomInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("CustomInterceptor before" );
Object result = invocation.proceed();
System.out.println("CustomInterceptor after");
return result;
}
}
複製程式碼
1.1.3 配置xml
建立aop.xml
,放在resources目錄下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
default-lazy-init="false" default-autowire="byName">
<!-- 實現來org.aopalliance.intercept.MethodInterceptor的攔截器 -->
<bean id="customInterceptor" class="com.xxx.yyy.CustomInterceptor"/>
<bean id="mockService" class="com.xxx.yyy.MockServiceImpl"/>
<aop:config proxy-target-class="true">
<aop:pointcut id="interceptorPointCuts" expression="execution(* com.xxx.yyy..*.*(..))"/>
<aop:advisor advice-ref="customInterceptor" pointcut-ref="interceptorPointCuts"/>
</aop:config>
</beans>
複製程式碼
1.1.4 執行
public class Main {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
MockService mockService = (MockService) context.getBean("mockService");
mockService.hello("mock");
}
}
複製程式碼
返回:
CustomInterceptor before
execute hello
CustomInterceptor after
複製程式碼
1.2 AOP實現過程
Spring環境啟動過程中,會呼叫AbstractApplicationContext.refresh()
,AOP的實現流程,也就是從這裡開始。
- 1 在
obtainFreshBeanFactory()
執行過程中,載入aop.xml,並根據namespace找到aop
對應的NamespaceHandler:AopNamespaceHandler
; - 2
AopNamespaceHandler
中,找到config標籤對應的BeanDefinitionParser的實現物件,也就是ConfigBeanDefinitionParser
; - 3 執行
ConfigBeanDefinitionParser.parse
,有兩個作用:- 以
AspectJAwareAdvisorAutoProxyCreator
註冊BeanDefinition; - 解析
pointcut
,advisor
等標籤,並將相關物件註冊為BeanDefinition。
- 以
- 4 註冊BeanPostProcessor:
AspectJAwareAdvisorAutoProxyCreator
是BeanPostProcessor的實現類AbstractAutoProxyCreator
的子類。註冊BeanPostProcessor後,AspectJAwareAdvisorAutoProxyCreator
會在Spring建立bean的代理過程中呼叫。 - 5 建立proxy,並用advisor增強,主要有幾步:
- 建立代理;
- 查詢匹配的advisor;
- 增強代理。
2 AopNamespaceHandler
Spring環境的載入,需要呼叫AbstractApplicationContext.refresh()。
在refresh()方法中,執行ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
建立BeanFacotry的時候,載入並解析xml資源。
在這個過程中,會呼叫BeanDefinitionParserDelegate.parseCustomElement
進行擴充套件標籤的解析:
public BeanDefinition parseCustomElement(Element ele,BeanDefinition containingBd) {
// 獲取namespace
String namespaceUri = getNamespaceURI(ele);
// 根據檔案META-INF/spring.handlers,獲取對應的NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]",ele);
return null;
}
// 呼叫NamespaceHandler.parse方法,返回BeanDefinition
return handler.parse(ele,new ParserContext(this.readerContext,this,containingBd));
}
複製程式碼
詳細過程可參考Spring自定義標籤配置的原始碼解析與實現。
對於<aop:config/>
,Spring會根據xmlns
去META-INF/spring.handlers
檔案中查詢相應的namespace解析類:
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
。
在AopNamespaceHandler
中:
registerBeanDefinitionParser("config",new ConfigBeanDefinitionParser());
所以:
aop
namespace的解析類是AopNamespaceHandler
-
<aop:config/>
標籤的解析類是ConfigBeanDefinitionParser
,在ConfigBeanDefinitionParser
中,<aop:config/>
定義的各個元素被解析為BeanDefinition
。
3 ConfigBeanDefinitionParser
ConfigBeanDefinitionParser
實現了BeanDefinitionParser
介面,在parse(Element element,ParserContext parserContext)
方法中,實現了兩部分功能:
- 1 向Spring環境註冊一個BeanDefinition:
AspectJAwareAdvisorAutoProxyCreator
; - 2 將xml配置的pointcut,advisor等解析為一系列BeanDefinition。
@Override
@Nullable
public BeanDefinition parse(Element element,ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(),parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 註冊AspectJAwareAdvisorAutoProxyCreator為BeanDefinition
configureAutoProxyCreator(parserContext,element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
// 解析pointcut
parsePointcut(elt,parserContext);
}
else if (ADVISOR.equals(localName)) {
// 解析advisor
parseAdvisor(elt,parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt,parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
複製程式碼
其中:
private static final String POINTCUT = "pointcut";
private static final String ADVISOR = "advisor";
private static final String ASPECT = "aspect";
複製程式碼
3.1 AspectJAwareAdvisorAutoProxyCreator
3.1.1 作用
-
AspectJAwareAdvisorAutoProxyCreator
是AbstractAutoProxyCreator
的子類; - AbstractAutoProxyCreator實現了介面
BeanPostProcessor
; - AbstractAutoProxyCreator在
postProcessAfterInitialization
的實現中,呼叫wrapIfNecessary
進行bean代理。
@Override
public Object postProcessAfterInitialization(@Nullable 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;
}
複製程式碼
Spring在例項化bean的過程中,會呼叫BeanPostProcessor
對bean生成前後進行處理,aop利用這一點:
呼叫AbstractAutoProxyCreator.postProcessAfterInitialization
方法,根據pointcut
查詢到相應的advisor
,對bean進行代理。
3.1.2 註冊BeanDefinition
程式碼執行流程:
-
1 ConfigBeanDefinitionParser.configureAutoProxyCreator;
-
2 AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext,element);
public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext,Element sourceElement) { // 註冊BeanDefinition BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(),parserContext.extractSource(sourceElement)); // 設定class-proxy useClassProxyingIfNecessary(parserContext.getRegistry(),sourceElement); registerComponentIfNecessary(beanDefinition,parserContext); } 複製程式碼
-
3 AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary;
-
4 AopConfigUtils.registerOrEscalateApcAsRequired:
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
//// 省略程式碼
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME,beanDefinition);
複製程式碼
最終生成了
AspectJAwareAdvisorAutoProxyCreator
的BeanDefinition,beanName為org.springframework.aop.config.internalAutoProxyCreator
。同時,
useClassProxyingIfNecessary
方法中,根據**aop:config/**中的proxy-target-class
,設定了AspectJAwareAdvisorAutoProxyCreator的一個父類ProxyConfig
的proxyTargetClass
屬性。
3.2 解析pointcut
解析<aop:pointcut id="interceptorPointCuts" expression="execution(* com.xxx.yyy..*.*(..))"/>
,註冊AbstractExpressionPointcut
的BeanDefinition。
3.2.1 parsePointcut
private AbstractBeanDefinition parsePointcut(Element pointcutElement,ParserContext parserContext) {
String id = pointcutElement.getAttribute(ID);
// 獲取表示式 配置中的 expression="execution(* com.xxx.yyy..*.*(..))"
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
// 使用AspectJExpressionPointcut,為pointcut建立BeanDefinition,
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
if (StringUtils.hasText(pointcutBeanName)) {
// 以id為beanName註冊AspectJExpressionPointcut為bean.
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName,pointcutDefinition);
}
else {
// 自動生成beanName註冊AspectJExpressionPointcut為bean.
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName,pointcutDefinition,expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
複製程式碼
3.2.2 createPointcutDefinition
- 1
aop:pointcut
解析為AspectJExpressionPointcut
物件。 - 2
AspectJExpressionPointcut extends AbstractExpressionPointcut
- 3
expression
是AbstractExpressionPointcut
的屬性
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION,expression);
return beanDefinition;
}
複製程式碼
3.3 解析advisor
解析<aop:advisor advice-ref="customInterceptor" pointcut-ref="interceptorPointCuts"/>
,註冊DefaultBeanFactoryPointcutAdvisor
的BeanDefinition。
3.3.1 parseAdvisor
- 1 呼叫
createAdvisorBeanDefinition
建立advisor; - 2 呼叫
parsePointcutProperty
獲取pointcut。
private void parseAdvisor(Element advisorElement,ParserContext parserContext) {
// 1 建立bean : DefaultBeanFactoryPointcutAdvisor
AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement,parserContext);
String id = advisorElement.getAttribute(ID);
try {
this.parseState.push(new AdvisorEntry(id));
String advisorBeanName = id;
// 2 註冊bean : DefaultBeanFactoryPointcutAdvisor
if (StringUtils.hasText(advisorBeanName)) {
parserContext.getRegistry().registerBeanDefinition(advisorBeanName,advisorDef);
}
else {
advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
}
// 3 解析 pointcut-ref="interceptorPointCuts"
Object pointcut = parsePointcutProperty(advisorElement,parserContext);
if (pointcut instanceof BeanDefinition) {
// 返回的是有`pointcut`構造的BeanDefinition(AspectJExpressionPointcut物件),則設定`DefaultBeanFactoryPointcutAdvisor.pointcut = pointcut`
advisorDef.getPropertyValues().add(POINTCUT,pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName,advisorDef,(BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {
// 返回的是beanName,則設定`DefaultBeanFactoryPointcutAdvisor.pointcut`為一個執行時Bean引用。
advisorDef.getPropertyValues().add(POINTCUT,new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName,advisorDef));
}
}
finally {
this.parseState.pop();
}
}
複製程式碼
3.3.2 createAdvisorBeanDefinition
- 1 建立
DefaultBeanFactoryPointcutAdvisor
的BeanDefinition,DefaultBeanFactoryPointcutAdvisor是PointcutAdvisor
的一個實現; - 2 解析
advice-ref
獲取advisor的Bean的beanName,即aop.xml中的customInterceptor。 - 3
DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor
,使用advice-ref
設定adviceBeanName
屬性,即前面的customInterceptor
。
private static final String ADVICE_BEAN_NAME = "adviceBeanName";
private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement,ParserContext parserContext) {
// 建立`DefaultBeanFactoryPointcutAdvisor`的BeanDefinition;
RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(advisorElement));
// 解析`advice-ref`獲取advice的Bean的beanName;
String adviceRef = advisorElement.getAttribute(ADVICE_REF);
if (!StringUtils.hasText(adviceRef)) {
parserContext.getReaderContext().error(
"'advice-ref' attribute contains empty value.",advisorElement,this.parseState.snapshot());
}
else {
// 設定AbstractBeanFactoryPointcutAdvisor的adviceBeanName屬性
advisorDefinition.getPropertyValues().add(
ADVICE_BEAN_NAME,new RuntimeBeanNameReference(adviceRef));
}
if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY,advisorElement.getAttribute(ORDER_PROPERTY));
}
return advisorDefinition;
}
複製程式碼
3.3.3 parsePointcutProperty
- 1 屬性有
pointcut
,則使用expression呼叫createPointcutDefinition,構造AspectJExpressionPointcut的bean後直接返回。 - 2 否則返回
pointcut-ref
指定的bean作為Pointcut。
所以:pointcut優先於 pointcut-ref,有pointcut就不再解析pointcut-ref。
private Object parsePointcutProperty(Element element,ParserContext parserContext) {
if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
parserContext.getReaderContext().error(
"Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",element,this.parseState.snapshot());
return null;
}
else if (element.hasAttribute(POINTCUT)) {
// 屬性有`pointcut`,則使用expression呼叫createPointcutDefinition,構造AspectJExpressionPointcut的bean後直接返回。
String expression = element.getAttribute(POINTCUT);
AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(element));
// 返回BeanDefinition
return pointcutDefinition;
}
else if (element.hasAttribute(POINTCUT_REF)) {
String pointcutRef = element.getAttribute(POINTCUT_REF);
if (!StringUtils.hasText(pointcutRef)) {
parserContext.getReaderContext().error(
"'pointcut-ref' attribute contains empty value.",this.parseState.snapshot());
return null;
}
// 返回pointcut-ref的beanName
return pointcutRef;
}
else {
parserContext.getReaderContext().error(
"Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",this.parseState.snapshot());
return null;
}
}
複製程式碼
3.4 解析過程中註冊的BeanDefinition
- BeanPostProcessor :
AspectJAwareAdvisorAutoProxyCreator
,beanName是org.springframework.aop.config.internalAutoProxyCreator
; - pointcut:
AbstractExpressionPointcut
,設定了expression屬性; - advisor:
DefaultBeanFactoryPointcutAdvisor
,pointcut屬性設定為AbstractExpressionPointcut
。
4 註冊BeanPostProcessor
在AbstractApplicationContext.refresh()方法中,建立ConfigurableListableBeanFactory
後,會執行registerBeanPostProcessors
向Spring環境註冊BeanPostProcessor
。
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
複製程式碼
AspectJAwareAdvisorAutoProxyCreator
在這個時候被加入到用於處理bean建立的BeanPostProcessor列表中。
簡要過程如下:
- 1 呼叫
PostProcessorRegistrationDelegate.registerBeanPostProcessors
; - 2 通過
beanFactory.getBean(ppName,BeanPostProcessor.class);
獲取BeanPostProcessor列表; - 3 執行
beanFactory.addBeanPostProcessor(postProcessor)
。
5 建立Bean並增強
5.1 createProxy
Spring建立Bean,是在AbstractAutowireCapableBeanFactory.doCreateBean
方法中:
- 在
AbstractAutowireCapableBeanFactory.doCreateBean
中呼叫了initializeBean
:
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName,mbd,instanceWrapper);
exposedObject = initializeBean(beanName,exposedObject,mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(),"Initialization of bean failed",ex);
}
}
複製程式碼
- 在
initializeBean
中:
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);
}
複製程式碼
-
applyBeanPostProcessorsAfterInitialization
執行了BeanPostProcessor.postProcessAfterInitialization方法:
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean,String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result,beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
複製程式碼
-
AbstractAutoProxyCreator.postProcessAfterInitialization
就在這裡執行:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean,cacheKey);
}
}
return bean;
}
複製程式碼
- 在
wrapIfNecessary
中使用advisor執行createProxy:
// Create proxy if we have advice.
// 1 查詢advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(),null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey,Boolean.TRUE);
// 2 建立proxy,並使用advisor進行增強
Object proxy = createProxy(
bean.getClass(),specificInterceptors,new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey,proxy.getClass());
return proxy;
}
複製程式碼
5.2 查詢匹配的advisor
AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean
是一個抽象方法,由子類AbstractAdvisorAutoProxyCreator
實現。
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
呼叫了findEligibleAdvisors
,主要實現兩個流程:
- 1 獲取候選的advisors;
- 2 過濾出匹配的advisors。
/*
beanClass:要代理的類
beanName:當前要代理的bean的beanName
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass,String beanName) {
// 1 獲取候選的advisors
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2 過濾出匹配的advisors
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors,beanClass,beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
複製程式碼
5.2.1 findCandidateAdvisors
呼叫BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
,獲取到所有實現了Advisor介面的Bean,主要程式碼片段如下:
-
1 找到是有實現了Advisor介面的beanName:
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory,Advisor.class,true,false);
-
2 根據beanName獲取Bean:
List<Advisor> advisors = new LinkedList<>(); .... advisors.add(this.beanFactory.getBean(name,Advisor.class)); .... return advisors; 複製程式碼
5.2.2 findAdvisorsThatCanApply
過濾出匹配的Advisor,主要通過AopUtils.findAdvisorsThatCanApply,呼叫canApply
實現:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors,Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
for (Advisor candidate : candidateAdvisors) {
// 呼叫 canApply
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;
}
// 呼叫canApply
if (canApply(candidate,clazz,hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
複製程式碼
5.2.3 canApply
- 1 如果介面是
IntroductionAdvisor
,則呼叫IntroductionAdvisor.ClassFilter.matchs進行判斷; - 2 如果介面是
PointcutAdvisor
(比如前面建立的DefaultBeanFactoryPointcutAdvisor),則先呼叫PointcutAdvisor.ClassFilter.matches進行判斷,再MethodMatcher.getMethodMatcher()進行判斷。
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 {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc,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<>(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,hasIntroductions)) ||
methodMatcher.matches(method,targetClass)) {
return true;
}
}
}
return false;
}
複製程式碼
5.3 使用advisor增強代理
在AbstractAutoProxyCreator.createProxy
中實現:
- 1 建立ProxyFactory
- 2 判斷proxyTargetClass
- 3 buildAdvisors
- 4 執行getProxy
protected Object createProxy(Class<?> beanClass,@Nullable String beanName,@Nullable Object[] specificInterceptors,TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory,beanClass);
}
// 建立ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 判斷proxyTargetClass
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass,beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass,proxyFactory);
}
}
// buildAdvisors
Advisor[] advisors = buildAdvisors(beanName,specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 執行getProxy
return proxyFactory.getProxy(getProxyClassLoader());
}
複製程式碼
5.3.1 DefaultAopProxyFactory.createAopProxy
proxyFactory.getProxy
中,需要一個AopProxy
去實現,AopProxy
的建立,在DefaultAopProxyFactory
中,返回一個JdkDynamicAopProxy
或一個CglibAopProxy
。
@Override
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);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
複製程式碼
5.3.2 JdkDynamicAopProxy
JdkDynamicAopProxy實現了java.lang.reflect.InvocationHandler
介面,在invoke(Object proxy,Method method,Object[] args)
中實現代理。程式碼片段如下:
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
// Check whether we have any advice. If we don't,we can fallback on direct
// reflective invocation of the target,and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target,and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method,args);
retVal = AopUtils.invokeJoinpointUsingReflection(target,method,argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy,target,args,chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
複製程式碼
呼叫
ReflectiveMethodInvocation.proceed()
實現了代理。
5.3.3 ObjenesisCglibAopProxy
ObjenesisCglibAopProxy是CglibAopProxy
的子類,代理邏輯都實現在CglibAopProxy
裡。
CglibAopProxy中獲取Callback陣列時,建立了DynamicAdvisedInterceptor物件。
private Callback[] getCallbacks(Class<?> rootClass){
//省略程式碼
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
//省略程式碼
}
複製程式碼
DynamicAdvisedInterceptor
實現了org.springframework.cglib.proxy.MethodInterceptor
介面,在intercept
方法裡執行了代理:
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy,chain,methodProxy).proceed();
複製程式碼
CglibMethodInvocation是
ReflectiveMethodInvocation
的子類,所以也是呼叫ReflectiveMethodInvocation.proceed()
實現了代理。