第二类:【CgLib代理】
有关CgLib的代理实现,过程中有一个接口MethodInterceptor,在CgLib包与AOP alliance中都有定义,而意义却完全不同,文中加以了标记区分。
CgLib代理使用Demo
首先我们先来实现一个不依赖Spring框架的,单纯基于Cglib的AOP代理:
目标类:
@Component
public class TestAopTarget {
public void process() {
System.out.println("TestAopTarget.process()");
}
}
自定义的MethodInterceptor:
public class MyMethodIncerceptor implements MethodInterceptor {
/*
Object o:要增强的目标对象
Method method:拦截的方法
Object[] objects:参数列表
MethodProxy:对方法的代理
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("_____before");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("_____after");
return result;
}
}
测试类:
public static void main(final String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
//不依赖Spring的CgLib模式动态代理
Enhancer enhancer = new Enhancer();
//setSuperclass:设置要代理的类
enhancer.setSuperclass(TestAopTarget.class);
//setCallback:设置回调即MethodInterceptor的实现类
enhancer.setCallback(new MyMethodIncerceptor());
//create():生成一个代理对象
TestAopTarget testAopTarget = (TestAopTarget) enhancer.create();
testAopTarget.process();
}
输出结果:
_____before
TestAopTarget.process()
_____after
CgLib中AOP的实现是基于org.springframework.cglib.proxy包中Enhancer和MethodInterceptor(是CgLib包中的,不是AOP alliance中的同名接口)两个接口来实现的。
对于整个过程,我们可以概括为:
- 定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
- 创建Enhance、设置Callback为上述MethodInterceptor
- enhancer.create()创建代理
Spring框架中CgLib代理源码分析
在得到Advisors之后,通过proxyFactory.getProxy获取代理
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
假定createAopProxy中决定的实现类为ObjenesisCglibAopProxy
class ObjenesisCglibAopProxy extends CglibAopProxy
这次我们从getProxy开始看起
getProxy获取代理
此方法是在ObjenesisCglibAopProxy的父类CglibAopProxy中实现的
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
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 ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
方法包含的步骤:
- 准备及验证工作
- 获取目标类的全部接口
- 检查目标类中是否含有final修饰的方法
- 创建及配置Enhancer
Enhancer enhancer = createEnhancer();
- 获取拦截器链Callback
Callback[] callbacks = getCallbacks(rootClass);
- 生成代理类并创建代理(设置enhancer的callback值)
return createProxyClassAndInstance(enhancer, callbacks)
这个过程已经实现了我们上述总结的三个步骤:
定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
创建Enhance、设置Callback为上述MethodInterceptor
enhancer.create()创建代理
需要关注的过程:
- getCallbacks获取拦截器链
- createProxyClassAndInstance获取代理
1.getCallbacks获取MethodInterceptor拦截器(CgLib包中接口)链并包装为Callback
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimisation 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);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
}
else {
targetInterceptor = isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
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
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimisations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
// TODO: small memory optimisation here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
方法中:
- 将Advisor包装为DynamicAdvisedInterceptor
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
- 通过DynamicAdvisedInterceptor创建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
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
- 默认情况下isStatic && isFrozen为false,返回step 2 中callbacks;
重点在第1步:创建DynamicAdvisedInterceptor
1.1 创建MethodInterceptor(CgLIb包中的接口)
首先,DynamicAdvisedInterceptor类实现了MethodIntercepto
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable
那么其中一定会有intercept方法的实现,就是AOP具体的逻辑:
@Override
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) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
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())) {
// 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 = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
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) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
1.1.1 intercept()中:获取MethodInterceptor拦截器链(AOP alliance中的接口)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Spring AOP(五)【源码分析】Spring中JDK动态代理及其链式增强的实现中 1.2.1通过Advisors中的Advice获取(包装为)MethodInterceptor拦截器链(AOP alliance中的接口) ,描述了如何根据Advice获取MethodInterceptor。
1.1.2 intercept()中:创建一个MethodInvocation并调用proceed()
retVal =
new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)
.proceed();
CglibMethodInvocation类继承了ReflectiveMethodInvocation,可见它也是实现了AOP联盟中的MethodInvocation接口
private static class CglibMethodInvocation extends ReflectiveMethodInvocation
同样的,也是step1中的MethodInterceptor调用其proceed()表示执行当前拦截点。
这个过程与JDK中的相同,也是链式调用拦截点,可参考Spring AOP(五)【源码分析】Spring中JDK动态代理及其链式增强的实现中 1.2.3.2 执行MethodInvocation.proceed
1.1.3. 返回此MethodInvocation
2. createProxyClassAndInstance获取代理
这个方法是在子类ObjenesisCglibAopProxy中实现的:
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) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
proxyInstance = (this.constructorArgs != null ?
proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
proxyClass.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
方法中做了两件事:
- 通过Enhancer创建代理实例
- 将实例设置回调:传入的callback参数