docs/Spring全家桶/Spring源码分析/SpringAOP/SpringAop(四):jdk动态代理.md
һƪµǷ spring ڴ˴дķʽΪ jdk̬ cglibǽ spring Ķ̬
spring Ķ̬ǰ˽ jdk Ķ̬jdk ̬ҪӿڣΪӿڣ
IJdkDynamicProxy01
package org.springframework.learn.demo03;
public interface IJdkDynamicProxy01 {
void hello01();
}
IJdkDynamicProxy02
package org.springframework.learn.demo03;
public interface IJdkDynamicProxy02 {
void hello02();
}
ʵࣺ
JdkDynamicProxyImpl01
package org.springframework.learn.demo03;
public class JdkDynamicProxyImpl01 implements IJdkDynamicProxy01, IJdkDynamicProxy02{
@Override
public void hello01() {
System.out.println("hello01");
}
@Override
public void hello02() {
System.out.println("hello02");
}
}
JdkDynamicProxyImpl02
package org.springframework.learn.demo03;
public class JdkDynamicProxyImpl02 implements IJdkDynamicProxy01 {
@Override
public void hello01() {
System.out.println("hello01");
}
}
ҪעǣJdkDynamicProxyImpl01 ʵ IJdkDynamicProxy01 IJdkDynamicProxy02 ӿڣJdkDynamicProxyImpl02 ֻʵ IJdkDynamicProxy01 һ ӿڡ
һ InvocationHandler:
MyInvocationHandler
package org.springframework.learn.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
/** Ŀ */
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("ִзΪ:" + method.getName());
// ִ
Object rs = method.invoke(target,args);
return rs;
}
}
:
package org.springframework.learn.demo03;
import java.lang.reflect.Proxy;
public class Demo03Main {
public static void main(String[] args) {
System.out.println("------------bean01------------");
JdkDynamicProxyImpl01 bean01 = new JdkDynamicProxyImpl01();
Object obj1 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
// JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01, IJdkDynamicProxy02
// classΪ IJdkDynamicProxy01, IJdkDynamicProxy02
new Class<?>[]{ IJdkDynamicProxy01.class, IJdkDynamicProxy02.class },
new MyInvocationHandler(bean01));
// Խǿת
((IJdkDynamicProxy01) obj1).hello01();
((IJdkDynamicProxy02) obj1).hello02();
System.out.println("------------bean01------------");
Object obj2 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
// JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01, IJdkDynamicProxy02
// classΪ IJdkDynamicProxy01
new Class<?>[]{ IJdkDynamicProxy01.class },
new MyInvocationHandler(bean01));
((IJdkDynamicProxy01) obj2).hello01();
// 쳣java.lang.ClassCastException: class com.sun.proxy.$Proxy1 cannot be cast to class xxx
//((IJdkDynamicProxy02) obj2).hello02();
System.out.println("-----------bean02-------------");
JdkDynamicProxyImpl02 bean02 = new JdkDynamicProxyImpl02();
Object obj3 = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
// JdkDynamicProxyImpl01ʵ IJdkDynamicProxy01
// classΪ IJdkDynamicProxy01, IJdkDynamicProxy02
new Class<?>[]{ IJdkDynamicProxy01.class, IJdkDynamicProxy02.class },
new MyInvocationHandler(bean02));
((IJdkDynamicProxy01) obj3).hello01();
IJdkDynamicProxy02 proxy02 = (IJdkDynamicProxy02) obj3;
// 쳣java.lang.IllegalArgumentException: object is not an instance of declaring class
//proxy02.hello02();
}
}
н
ִзΪ:hello01
hello01
ִзΪ:hello02
hello02
------------bean01------------
ִзΪ:hello01
hello01
-----------bean02-------------
ִзΪ:hello01
hello01
Խ£
Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ĵڶĽӿڣǴĽӿִִͣΪ invoke()JdkDynamicProxyImpl01 ͬʱʵ IJdkDynamicProxy01 IJdkDynamicProxy02 ӿڣӿʱֻ IJdkDynamicProxy01 obj2 ǿתΪ IJdkDynamicProxy02 ʱͻᱨ ClassCastExceptionǿתʧܣ Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ǴĽӿͣJdkDynamicProxyImpl02 ֻʵ IJdkDynamicProxy01 ӿڣӿʱ IJdkDynamicProxy01 IJdkDynamicProxy02 obj3 ǿתΪ IJdkDynamicProxy02 ʱδ쳣ִ proxy02.hello02() ʱȴ java.lang.IllegalArgumentException: object is not an instance of declaring classͬ Proxy#newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) ǴĽӿͣĿءķ spring δģ
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// ȡĿʵֵĽӿ
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// Ƿequals()hashCode()
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// jdk
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
proxiedInterfacesֵĿʵֵнӿڣͬʱ spring ҲĽӿڣ SpringProxy``AdvisedЩһƪѾϸˣInvocationHandler Ϊ thisҲ JdkDynamicAopProxy Ķʵ JdkDynamicAopProxy ʵ InvocationHandler.ɵһֵķ֪jdk ̬ķ java.lang.reflect.InvocationHandler#invoke ִеģҲ JdkDynamicAopProxy#invokeǾ JdkDynamicAopProxy#invoke spring ִдġ
spring jdk ִ̬ JdkDynamicAopProxy#invoke
JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// ִе equals Ҫִ
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
// ִе hashCode Ҫִ
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// ִеclassDecoratingProxyҲҪִ
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// ж advisedexposeProxy ֵǷΪ true
// advisedexposeProxyԴ @EnableAspectJAutoProxy exposeProxy
// ָʱ@EnableAspectJAutoProxy(exposeProxy = true)´ִ
if (this.advised.exposeProxy) {
// ǰ proxy ŵ threadLocal
// (UserService (AopContext.currentProxy)).getUser() ʽ
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// ȡĿĿclass
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// aop advisor תΪжϸ÷ʹЩ淽
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
method, targetClass);
if (chain.isEmpty()) {
// Ϊգ÷ûбأֱִͨ
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// һö
MethodInvocation 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())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(...);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
Ϸ£
equals``hashcode ȣЩҪصע淽Ŀ귽ִУؼ£
// aop advisor תΪжϸ÷ʹЩ淽
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
method, targetClass);
// һö
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// ִУص
retVal = invocation.proceed();
MethodInterceptorڷִǰ getInterceptorsAndDynamicInterceptionAdvice(...)ȡִе淽ģҲ MethodInterceptor
AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method,
@Nullable Class<?>targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// ȡٷ
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
/**
* ȡ Interceptor£
*/
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// ȡ advisorsaopadvisors£
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// advisorPointcutAdvisorʹPointcutAdvisorPointcutƥ
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// жĵǷǰйˣйٽĿ귽ƥ䣬
// ûУٽһƥ䡣
if (config.isPreFiltered()
|| pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm)
.matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
// AdvisorתΪMethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
// interceptormethodMatcherװInterceptorAndDynamicMethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
// жΪIntroductionAdvisor͵AdvisorװΪInterceptor
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
// ṩʹԶתAdvisorתΪgetInterceptors()
// ʹӦAdapterĿAdvisorƥ䣬ƥϣͨgetInterceptor()
// ԶAdviceתΪMethodInterceptor
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
ǸϷܽ»ȡ MethodInterceptor Ĺ̹£
ȡĿе advisors
ÿ
advisor
̴
advisor PointcutAdvisorʹе Pointcut ƥ䣬ƥɹȡ MethodInterceptor أadvisor IntroductionAdvisorʹе ClassFilter ƥ䣬ƥɹȡ MethodInterceptor أMethodInterceptor أô MethodInterceptor λȡأǼ¿
// AdvisorAdapter ĵط
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
// adapter
public DefaultAdvisorAdapterRegistry() {
// @Before
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
// @AfterReturning
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
// @AfterThrowing
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
/**
* ȡadvisorӦMethodInterceptor
*/
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
// ȡǰadvisorMethodInterceptor
Advice advice = advisor.getAdvice();
// advice MethodInterceptorʵ
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//
// ʹ AdvisorAdapter advice תΪ MethodInterceptor
// adviceadapter adapter.getInterceptor ȡ MethodInterceptor
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
ܽ£
advice MethodInterceptorֱӽת MethodInterceptorAdvisorAdapter advice ת MethodInterceptor.adaptersspring Ϊṩ Adapter
@Before@AfterReturning@AfterThrowingAdapter ֻһܣ advice Ӧ MethodInterceptor MethodBeforeAdviceAdapter Ĵˣ
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
/**
* Ƿܴǰadvice
*/
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
/**
* ضӦMethodInterceptor
*/
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
Adapter ĹܼƣͲˣܽ¸עӦ advice``methodInterceptor
| ע | advice | methodInterceptor |
|---|---|---|
| @Before | AspectJMethodBeforeAdvice | MethodBeforeAdviceInterceptor |
| @After | AspectJAfterAdvice | AspectJAfterAdvice |
| @Around | AspectJAroundAdvice | AspectJAroundAdvice |
| @AfterReturning | AspectJAfterReturningAdvice | AfterReturningAdviceInterceptor |
| @AfterThrowing | AspectJAfterThrowingAdvice | ThrowsAdviceInterceptor |
ȡ MethodInterceptor Ϳʼзִˣֱӽ ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
// ִеǿִĿ귽
// ʹģʽеãʾǰѾִе
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// ȡһҪִе
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null
? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// ƥ䣬͵ķҲ淽
// MethodInterceptor#invokeٴ ReflectiveMethodInvocation#proceedֵ˵ǰ
return dm.interceptor.invoke(this);
}
else {
// ƥ䣬ݹõǰ
return proceed();
}
}
else {
// ע⣬IJ thisʾǰ
// MethodInterceptor#invokeٴ ReflectiveMethodInvocation#proceedֵ˵ǰ
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
/**
* Ŀ귽
*/
protected Object invokeJoinpoint() throws Throwable {
// ʹ÷ĿעﴫӦĿǴ
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
ϴĵʹģʽִ£
ͦôִеأ spring У֪ͨͣ@Before``@After``@AfterReturning``@AfterThrowing @Aroundһһ֪ͨεõġ
@BeforeMethodBeforeAdviceInterceptor#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// ִǰ֪ͨ
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// ִһ
return mi.proceed();
}
advice.before(xxx)
AspectJMethodBeforeAdvice#before
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
ȥ
AbstractAspectJAdvice#invokeAdviceMethod(JoinPointMatch, Object, Throwable)
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
/**
* ÷ִ
*/
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// Ϥjdk
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
return this.aspectJAdviceMethod.invoke(
this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (...) {
...
}
Կǵ jdk õġ
@AfterAspectJAfterAdvice#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// ִһ
return mi.proceed();
}
finally {
// 淽 finally 飬ʾһִУҲʹ÷
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@AfterReturningAfterReturningAdviceInterceptor#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// ִһ
Object retVal = mi.proceed();
// 淽¿
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
AspectJAfterReturningAdvice#afterReturning
public void afterReturning(@Nullable Object returnValue, Method method,
Object[] args, @Nullable Object target) throws Throwable {
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
// 淽Ȼǵ÷ִ
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
}
@AfterThrowingAspectJAfterThrowingAdvice#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// ReflectiveMethodInvocation#proceed
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
// 淽ֻ׳쳣ʱŻᱻ
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
@AroundAspectJAroundAdvice#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException(...);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 淽
return invokeAdviceMethod(pjp, jpm, null, null);
}
ʵֻ֪ͨʱһʵ֣
@Around(xxx)
public Object around(ProceedingJoinPoint p){
// ִĿ귽ǰIJ
...
// ִĿ귽һǹؼ
// ʵﲢִĿ귽յõ ReflectiveMethodInvocation#proceed
// ִһִĿ귽
Object o = p.proceed();
// ִĿ귽IJ
...
return o;
}
spring ִ֪ͨУҪΪ֣
ReflectiveMethodInvocation#proceed ִһִĿ귽ֵIJִдִеλã
@Before ֪ͨ1 ǰ2 ں@AfterReturning ֪ͨ2 ǰ1 ںִ 2 ʱ쳣1 Ͳִˣ@AfterThrowing ֪ͨ2 ǰ1 ں 1 Ƿ catch ִУֻз쳣1 ŻִУ@After ֪ͨ2 ǰ1 ں1 Ƿ finally ִУ finally ԣʹ쳣1 ִͬУ@Around ֪ͨ淽ָ 2 ִʱע @AfterReturning``@AfterThrowing @After ִ֪ͨʱ
⼸ִ֪ͨеġ
ͨԵķʽ spring ִ֪ͨ˳£
@AfterThrowing ֪ͨȵ mi.proceed() ִһȻ catch ִ淽ֻг쳣ʱ淽ŻִУmi.proceed() ʱִ @AfterReturning ִ֪ͨʱȵ mi.proceed() ִһȻִ淽mi.proceed() ʱִ @After ִ֪ͨʱȵ mi.proceed() ִһȻ finally ִ淽ʹ쳣淽ǻִУmi.proceed() ʱִ @Around ִ֪ͨʱֱִ淽 @Around ֪ͨ淽 ProceedingJoinPoint#proceed()ջǻִһmi.proceed() ʱִ @Before ִ֪ͨʱִ淽ٵ mi.proceed() ִһͼʾִ֪ͨй£
յִ˳
Ҫ jdk ִ̬й̣˸ִ֪ͨ˳ľȵˣһƪ½ cglib ִй̡
ԭӣhttps://my.oschina.net/funcy/blog/4696654 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע