docs/Spring全家桶/Spring源码分析/SpringAOP/SpringAop(五):cglib代理.md
һƪ spring jdK ̬ spring cglib
jdk Ȼṩ˶̬Ƕ̬һ㣺ûʵֽӿڣ jdk ̬Ϊ˽㣬spring cglib
cglib ײǻ asm ģҲֱӲֽ룬൱ڶ asm һװֱӲ룬Ҫ java ָֽļܽУֽɬѶһ㲻ֱӲ cglib װֽIJͱüˣ**¶ʹ cglib װõķֽ**
spring cglib λ spring-core ģ飺
asm cglib ˵
/**
* Spring's repackaging of
* ASM 7.0
* (with Spring-specific patches; for internal use only).
*
* <p>This repackaging technique avoids any potential conflicts with
* dependencies on ASM at the application level or from third-party
* libraries and frameworks.
*
* <p>As this repackaging happens at the class file level, sources
* and javadocs are not available here.
*/
package org.springframework.asm;
עһ䣺Spring's repackaging of ASM 7.0 spring asm7.0 ´.
/**
* Spring's repackaging of
* CGLIB 3.3
* (with Spring-specific patches; for internal use only).
*
* <p>This repackaging technique avoids any potential conflicts with
* dependencies on CGLIB at the application level or from third-party
* libraries and frameworks.
*
* <p>As this repackaging happens at the class file level, sources
* and javadocs are not available here.
*/
package org.springframework.cglib;
עһ䣺Spring's repackaging of CGLIB 3.3 spring CGLIB 3.3 ´.
ν´أ⣬ǽ asm7.0 CGLIB 3.3 ԴĸƵ spring Ŀ¡ spring û gradle ļ asm cglib ൱ jar ĿֱĿԴ룡
ʽʼ֮ǰ cglib νеġ
һࣺ
package org.springframework.learn.demo04;
public class CglibProxyService {
public void hello01() {
System.out.println("hello01");
}
}
һ MethodInterceptor jdk ̬е InvocationHandler
package org.springframework.learn.demo04;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
/** Ŀ */
private Object target;
public MyMethodInterceptor(Object target){
this.target = target;
}
@Override
public Object intercept(Object proxyObj, Method method, Object[] objects,
MethodProxy proxy) throws Throwable {
System.out.println("ִзΪ:" + method.getName());
return proxy.invoke(target, objects);
}
}
ࣺ
package org.springframework.learn.demo04;
import org.springframework.cglib.proxy.Enhancer;
/**
*
*
* @author fangchengyan
* @date 2020-11-01 9:23
*/
public class Demo04Main {
public static void main(String[] args) {
CglibProxyService target = new CglibProxyService();
MyMethodInterceptor interceptor = new MyMethodInterceptor(target);
Enhancer enhancer = new Enhancer();
// ø
enhancer.setSuperclass(CglibProxyService.class);
// callbackcallbackṩ MyMethodInterceptor
enhancer.setCallback(interceptor);
// ʹ enhancer
CglibProxyService proxy = (CglibProxyService)enhancer.create();
proxy.hello01();
}
}
У£
ִзΪ:hello01
hello01
Կ MyMethodInterceptor#intercept ִĿķ
ͬ jdk ̬ȽϺߴ߶ƣ
InvocationHandler InvocationHandlerߴʽһ
Ĵһʹ Enhangcer дһʹ÷װõķж
ӴԿ cglib ɶʱõIJ϶࣬ܽϷḻ
Enhangcer δԼ org.springframework.asm org.springframework.cglib µĴ룬Щ cglib ݣͲˡ
cglibspring δģ
CglibAopProxy#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "...");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Ŀм飬Ҫ
// 1\. Ŀ귽ʹfinalΣ
// 2\. Ŀ귽private͵ģ
// 3\. Ŀ귽ǰȨģ
// κһǰͲܱʱ÷ͻᱻԹ
validateClassIfNecessary(proxySuperClass, classLoader);
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// SuperclassҪ
enhancer.setSuperclass(proxySuperClass);
// AopProxyUtils.completeProxiedInterfaces()ҪĿΪҪɵĴ
// SpringProxyAdvisedDecoratingProxyҪʵֵĽӿڡӿڵ£
// 1\. SpringProxyһսӿڣڱǵǰɵĴSpringɵĴࣻ
// 2\. AdvisedSpringɴʹõԶڸýӿУ
// AdvisorAdviceԣ
// 3\. DecoratingProxyýӿڻȡǰĿClass͡
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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();
}
// ôиҪʹõProxyCallbackFilter.accept()
// ֵһһӦCallbackи±꣬Ҳ˵CallbackFilter
// ָ˴иҪʹCallbackеĸļ
enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(),
this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// ɴ
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (...) {
...
}
}
ϴ Enhancer ԣ classLoader``superclass``callbackFilter ȣ createProxyClassAndInstance(xxx)
ObjenesisCglibAopProxy#createProxyClassAndInstance
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
//
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
// ݴ࣬ʹ÷ɶ
if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
...
}
}
if (proxyInstance == null) {
try {
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException(...);
}
}
// callback
// ˶ callback ʱͨ CallbackFilter ȷʹĸ callback
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
ͨڵڶֵ demo04 ֪cglib ִУᾭ MethodInterceptor#intercept õģҲ Enhancer callback ԣ˽ callback Ļȡشλ CglibAopProxy#getCallbacks
CglibAopProxy#getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// ûԶĴcallbackУ @Before@Around@After淽
// DynamicAdvisedInterceptorе
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
Callback targetInterceptor;
// жҪ¶ǣʹAopContextýõThreadLocal
// ûͨAopContextȡĿ
if (exposeProxy) {
// жϱĶǷǾ̬ģǾ̬ģĿÿζʹøöɣ
// ĿǶ̬ģDynamicUnadvisedExposedInterceptorÿζһµ
// Ŀ֯Ĵ
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
// ΨһǷʹAopContext¶ɵĴ
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// ǰCallbackڲñķ
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
// ȡcallbackװΪһ
Callback[] mainCallbacks = new Callback[] {
// ûԼ
aopInterceptor, // for normal advice
// Ƿ¶
targetInterceptor, // invoke target without considering advice, if optimized
// κβ
new SerializableNoOp(), // no override for methods mapped to this
// ڴ洢Advisedķַ
targetDispatcher, this.advisedDispatcher,
// equalsõ
new EqualsInterceptor(this.advised),
// hashcodeõ
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// ĿǾ̬ģĵǹ̶ģĿл
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
// ȡĿ
List<Object> chain = this.advised
.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
// Եл
this.fixedInterceptorMap.put(method, x);
}
// ɵľ̬Callback
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
// fixedInterceptorOffset¼˵ǰ̬ĵʼλã
// ¼ôںʹCallbackFilterʱǾ̬ĵ
// ֱͨòȡӦĵֱԹǰĶ̬
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
ϴȽϳҪþǻȡ callbackȻ spring ṩڶ callbackԶ֪ͨص callback ֻһ DynamicAdvisedInterceptor callback CglibAopProxy.DynamicAdvisedInterceptor#intercept УڴеԶִ֪ͨеġ
һǵõ cglib Ĵ淽ִеġ
cglib 淽ִ CglibAopProxy.DynamicAdvisedInterceptor#intercept
CglibAopProxy.DynamicAdvisedInterceptor#intercept
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
// ͨTargetSourceȡĿ
TargetSource targetSource = this.advised.getTargetSource();
try {
// жҪ¶ǰõThreadLocal
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// ȡĿĵ
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 {
// 裺
// 1\. ִnew CglibMethodInvocation()
// 2\. ִCglibMethodInvocation#proceed
retVal = new CglibMethodInvocation(proxy, target, method, args,
targetClass, chain, methodProxy).proceed();
}
// ԷֵдֵǵǰĿôɵĴأ
// ֵΪգҷֵǷvoidĻͣ׳쳣
// ϣֱӽɵķֵ
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
ִ new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed()ȥ
CglibAopProxy.CglibMethodInvocation#proceed
public Object proceed() throws Throwable {
try {
return super.proceed();
}
catch (...) {
....
}
}
ֱӵõǸķCglibAopProxy.CglibMethodInvocation ĸ˭أһȥ־Ȼ ReflectiveMethodInvocation``super.proceed() õ ReflectiveMethodInvocation#proceed
һ ƪУǾϸ ReflectiveMethodInvocation#proceed ĵụ̀ڣ cglib ִеҲͬĴ룬һִй̾Ͳظˡ
һͼ˵ִ֪ͨй̣
յִ˳
ķ cglib ִйִ̣λ CglibAopProxy.DynamicAdvisedInterceptor#interceptյõ ReflectiveMethodInvocation#proceed jdk ִ̬ͬ
ԭӣhttps://my.oschina.net/funcy/blog/4696655 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע