Spring原始碼分析:AOP分析(一)
前言
Spring 的兩大核心,一是IOC,我們之前已經學習過,而另一個則是大名鼎鼎的 AOP,AOP的具體概念我就不介紹了,我們今天重點是要從原始碼層面去看看 spring 的 AOP 是如何實現的。
在Spring AOP實現中,使用的核心技術是動態代理,生成代理類有兩種策略:jdk動態代理和cglib動態代理。
下面簡要的談一談這兩種代理
JDK動態代理
jdk 代理是基於介面實現的,最好的學習方式當然是看原始碼,因此這裡我們可以將生成的代理類匯出,再通過反編譯檢視程式碼,看看裡面是怎麼回事。
定義一個UserService
介面:
public interface UserService { void add(); }
實現類UserServiceImpl
:
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("--------------------add----------------------");
}
}
編寫自己的InvocationHandler
:
public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { super(); this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-----------------begin "+method.getName()+"-----------------"); Object result = method.invoke(target, args); System.out.println("-----------------end "+method.getName()+"-----------------"); return result; } public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this); } }
將代理類匯出:
public class JdkProxyTest { public static void main(String[] args) { //生成的代理類儲存到磁碟 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); UserService service = new UserServiceImpl(); MyInvocationHandler handler = new MyInvocationHandler(service); UserService proxy = (UserService) handler.getProxy(); proxy.add(); } }
現在JDK動態代理已經完成了,現在我們來看看生成的代理類反編譯結果:
public final class $Proxy0 extends Proxy implements UserService {
//省略部分程式碼
private static Method m3;
public $Proxy0(InvocationHandler h) throws {
super(h);
}
//代理類的add 方法
public final void add() throws {
try {
//呼叫 InvocationHandler 的invoke方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m3 = Class.forName("com.study.spring.proxy.jdk.UserService").getMethod("add", new Class[0]);
//省略部分程式碼
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
通過程式碼很容易就明白了,JDK動態代理是使用介面生成新的實現類,實現類裡面則委託給InvocationHandler,InvocationHandler裡面則呼叫被代理的類方法。
CGLIB 動態代理
同JDK代理一樣,通過程式碼來理解
編寫方法攔截器:
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback( this);
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("-----------------begin "+method.getName()+"-----------------");
Object result = proxy.invokeSuper(obj, args);
System.out.println("-----------------end "+method.getName()+"-----------------");
return result;
}
}
匯出代理類:
public class CglibProxyTest {
public static void main(String[] args){
//生成代理類到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "com/study/spring/proxy/cglib");
UserServiceImpl service = new UserServiceImpl();
CglibProxy cp = new CglibProxy();
UserService proxy = (UserService) cp.getProxy(service.getClass());
proxy.add();
}
}
反編譯代理類,由於程式碼有點長,因此刪減了一部分:
public class UserServiceImpl$$EnhancerByCGLIB$$d166e24d extends UserServiceImpl implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$add$0$Method;
private static final MethodProxy CGLIB$add$0$Proxy;
final void CGLIB$add$0() {
super.add();
}
public final void add() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
var10000.intercept(this, CGLIB$add$0$Method, CGLIB$emptyArgs, CGLIB$add$0$Proxy);
} else {
super.add();
}
}
public UserServiceImpl$$EnhancerByCGLIB$$d166e24d() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var1 = (UserServiceImpl$$EnhancerByCGLIB$$d166e24d)var0;
if(!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if(var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if(CGLIB$STATIC_CALLBACKS == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
通過程式碼我們知道,Cglib是通過直接繼承被代理類
從代理類裡面可知道對於原來的add函式,代理類裡面對應了兩個函式分別是add 和CGLIB$add$0
其中後者是在方法攔截器裡面呼叫的,前者則是我們使用代理類時候呼叫的函式。當我們程式碼呼叫add時候,會具體呼叫到方法攔截器的intercept方法。
整體上JDK代理和CGLIB代理思想上都是差不多的,jdk基於介面,cglib基於繼承(因此方法不能被final修飾)。
深入 AOP 原始碼實現
閱讀原始碼很好用的一個方法就是跑程式碼來除錯,因為自己一行一行地看的話,比較枯燥,而且難免會漏掉一些東西,為了更方便的除錯程式碼,這裡我們採用xml配置方式,簡要的實現aop功能。
同樣使用上面的 UserService 和UserServiceImpl類
建立一個Advice,這裡實現 MethodBeforeAdvice介面:
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable{
System.out.println(o.getClass() + ":"+method.getName()+" 方法準備執行");
}
}
xml:
<bean id="userService" class="com.study.spring.aop.UserServiceImpl"/>
<!--advice-->
<bean id="beforeAdvice" class="com.study.spring.aop.BeforeAdvice" />
<bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean" >
<!--代理介面類-->
<property name="proxyInterfaces" value="com.study.spring.aop.UserService"/>
<!--代理實現類-->
<property name="target" ref="userService"/>
<!--走CGLIB代理-->
<!--<property name="proxyTargetClass" value="true"/>-->
<!--配置攔截器,這裡可以配置advice,advisor,interceptor-->
<property name="interceptorNames">
<!--引用我們beforeAdvice-->
<list><value>beforeAdvice</value></list>
</property>
</bean>
測試程式碼:
public void TestAOP(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
ProxyFactoryBean abcProxy = (ProxyFactoryBean) context.getBean("&userServiceProxy");
UserService userService= (UserService) abcProxy.getObject();
userService.add();
//實際獲取的是被FactoryBean 包裝後的bean
userService = (UserService) context.getBean("userServiceProxy");
userService.add();
}
執行結果這裡就不展示了,在呼叫add 方法前,都會先執行我們的BeforeAdvice,AOP生效。
上面的程式碼中又涉及到了FactoryBean,這個我們在前面講IOC的時候已經說過了,這裡當然也就不在說了,不知道的朋友,可以自行再去看看。
ProxyFactoryBean
程式碼很簡單,配置也很簡單,核心程式碼其實也就是ProxyFactoryBean
,它是一個FactoryBean,那麼在getBean的時候,會呼叫該FactoryBean的getObject 方法,因此 ProxyFactoryBean 的 getObject 方法就是我們的入口了。
getObject
public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
該方法很重要,首先初始化Advice鏈,然後獲取單例,這裡返回的就是我們最初看到的代理bean。這裡的初始化Advice鏈的重要作用就是將其連線起來,基本實現就是迴圈我們在配置檔案中(interceptorNames)配置的攔截器,按照連結串列的方式連線起來。
initializeAdvisorChain
/**
* Create the advisor (interceptor) chain. Advisors that are sourced
* from a BeanFactory will be refreshed each time a new prototype instance
* is added. Interceptors added programmatically through the factory API
* are unaffected by such changes.
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
for (String name : this.interceptorNames) {
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
//根據name 獲取bean
advice = this.beanFactory.getBean(name);
}
else {
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
程式碼比較簡單,核心思想就是初始化我們配置的攔截器,裡面會遞迴呼叫getBean 方法。
我們著重關注下面的方法 getSingletonInstance();
getSingletonInstance
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
該方法是同步方法,防止併發錯誤,因為有共享變數。首先返回一個包裝過的目標物件,重要的一行是 getProxy(createAopProxy())
,先建立AOP,再獲取代理。我們先看 crateAopProxy。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
該方法返回一個AopProxy 型別的例項,我們看看該介面:
這是該介面的繼承圖,分別是 JdkDynamicAopProxy 動態代理和 CglibAopProxy 代理。
我們繼續看 createAopProxy 方法,該方法主要邏輯是建立一個AOP 工廠,預設工廠是 DefaultAopProxyFactory
DefaultAopProxyFactory
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
該類的 createAopProxy 方法則根據 ProxyFactoryBean 的一些屬性來決定建立哪種代理:
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);
}
}
到這裡,我們知道 createAopProxy 方法有可能返回 JdkDynamicAopProxy 例項,也有可能返回 ObjenesisCglibAopProxy 例項,這裡總結一下:
如果被代理的目標類實現了一個或多個自定義的介面,那麼就會使用 JDK 動態代理,如果沒有實現任何介面,會使用 CGLIB 實現代理,如果設定了 proxy-target-class=“true”,那麼通常都會使用 CGLIB。
JDK 動態代理基於介面,所以只有介面中的方法會被增強,而 CGLIB 基於類繼承,需要注意就是如果方法使用了 final 修飾,或者是 private 方法,是不能被增強的。
我們分別來看下兩個 AopProxy 實現類的 getProxy(classLoader) 實現。
JdkDynamicAopProxy
getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
java.lang.reflect.Proxy.newProxyInstance(…) 方法需要三個引數,第一個是 ClassLoader,第二個引數代表需要實現哪些介面,第三個引數最重要,是 InvocationHandler 例項,我們看到這裡傳了 this,因為 JdkDynamicAopProxy 本身實現了 InvocationHandler 介面。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
}
InvocationHandler 只有一個方法,當生成的代理類對外提供服務的時候,都會回到這個方法中:
invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
// 代理equals 方法
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
// 代理hashCode 方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 如果設定了 exposeProxy,那麼將 proxy 放到 ThreadLocal 中
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 建立一個 chain,包含所有要執行的 advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// chain 是空的,說明不需要被增強
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, 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())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
核心邏輯不算複雜,重點分析建立advice chain,然後呼叫方法程式碼那裡(44行~57行),可以進行斷點除錯,觀察一下執行流程,這裡就不繼續追下去了,感興趣的讀者自己去深入探索下,不是很難。
說完了 JDK 動態代理 JdkDynamicAopProxy,我們再來看一下 CGLIB 的代理實現 ObjenesisCglibAopProxy。
ObjenesisCglibAopProxy 繼承了 CglibAopProxy,而 CglibAopProxy 繼承了 AopProxy。
CglibAopProxy
在前面我們知道得到AopProxy後,會呼叫getProxy 方法,因此這裡我們直接就來看看該方法。
getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
從上面程式碼中,可以看到對CGLIB的使用,比如對Enhancer物件的配置,以及通過Enhancer 物件生成代理物件的過程。在這個生成代理物件的過程中,需要注意的是對Enhancer物件callback回撥的設定,正是這些回撥封裝了Spring AOP的實現,就像前面介紹的JDK的Proxy物件的invoke回撥方法一樣。在Enhancer的callback回撥設定中,實際上是通過設定DynamicAdvisedInterceptor攔截器來完成AOP功能的。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
...
}
DynamicAdvisedInterceptor 引數中的 this.advised 是一個AdvisedSupport
例項,這個是在建立AOpProxy的時候傳入的。
現在切入點在 DynamicAdvisedInterceptor 類了
DynamicAdvisedInterceptor
核心方法便是intercept 方法了,類似invoke 方法。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//回去攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
//如果攔截器為空,則直接進行方法呼叫
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
//攔截器呼叫,方法呼叫
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
方法邏輯和JdkDynamicAopProxy 中的invoke 方法是差不多的,這裡就不多說了。
總結
以ProxyFactoryBean為例,通過簡單的配置,對Spring AOP的基本實現和工作流程進行了簡單的梳理,通過ProxyFactoryBean 得到AopProxy物件。
通過使用AopProxy物件封裝target目標物件之後,ProxyFactoryBean的getObject方法得到的物件就不是一個普通的Java物件了,而是一個AoppProxy代理物件。在ProxyFactoryBean中配置的target目標物件,這時已經不會讓應用直接呼叫其方法實現,而是作為AOP實現的一部分。對target目標物件的方法呼叫會首先被AopProxy代理物件攔截,對於不同的AopProxy代理物件生成方法,會使用不同的攔截回撥入口。例如,對於JDK的AopProxy代理物件,使用是InvocationHandler的invoke回撥入口;而對於CGLIB的AopProxy代理物件,使用的是設定好的callback回撥,在這些callback 回撥中,對於AOP實現,是通過DynamicAdvisedInterceptor 來完成的,而DynamicAdvisedInterceptor的回撥入口是intercept方法。
參考
Spring 技術內幕