[TOC]
動(dòng)態(tài)代理
JDK的動(dòng)態(tài)代理是通過實(shí)現(xiàn)目標(biāo)類的接口來創(chuàng)建代理類,借助里式替換原則通過聚合目標(biāo)類,在接口方法內(nèi)部委托目標(biāo)類的接口方法來達(dá)到控制對(duì)目標(biāo)方法的訪問的目的。
CGLIB則是通過繼承來實(shí)現(xiàn)代理,具體邏輯是繼承目標(biāo)類創(chuàng)建一個(gè)子類,然后重寫目標(biāo)方法,在內(nèi)部調(diào)用父類方法來達(dá)到代理的目的。
CGLIB示例
- 目標(biāo)類:
public class MyClass {
public void method() {
System.out.println("MyClass.method()");
}
}
- Testcase
package aop.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class Main {
@Test
public void testCGLIB() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("before");
System.out.println("method Name:" + method.getName());
// 調(diào)用父類方法來完成實(shí)際業(yè)務(wù)邏輯
proxy.invokeSuper(target, args);
System.out.println("after");
return null;
}
});
MyClass my = (MyClass) enhancer.create();
my.method();
}
}
JDK動(dòng)態(tài)代理示例
- 實(shí)現(xiàn)接口的目標(biāo)類
public interface MyInterface {
void method();
}
public class MyClassWithInterface implements MyInterface {
@Override
public void method() {
System.out.println("MyClassWithInterface.method()");
}
}
- TestCase
@Test
public void testJDKProxy() {
final MyClassWithInterface target = new MyClassWithInterface();
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
// 實(shí)際的業(yè)務(wù)邏輯還是委托給目標(biāo)類的
method.invoke(target, args);
System.out.println("after");
return null;
}
});
proxy.method();
}
Spring AOP
Spring AOP是基于動(dòng)態(tài)代理的,代理方式包括以上兩種,所以只能攔截方法,且不能攔截未實(shí)現(xiàn)接口的final class。
AOP生成代理的入口
在Spring中,bean的創(chuàng)建是交給IOC容器的,從上面動(dòng)態(tài)代理的使用來看,基于接口的JDK代理的代理對(duì)象的生成是需要持有目標(biāo)對(duì)象的。AOP是基于BeanPostProcessor在createBean邏輯中的回調(diào),涉及的主要后處理器為org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator,調(diào)用時(shí)機(jī)是在目標(biāo)bean實(shí)例化之后,執(zhí)行initializeBean()初始化內(nèi)部中執(zhí)行postProcessAfterInitialization()回調(diào)。
調(diào)用棧為:doCreateBean()->initializeBean()->applyBeanPostProcessorsAfterInitialization()->org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization()->wrapIfNecessary()->createProxy.
- wrapIfNecessary
開啟了AOP自動(dòng)代理之后,所有bean的創(chuàng)建都會(huì)進(jìn)入這一步判斷是否需要wrap,因?yàn)锽eanPostProcessor是全局的。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice. // 判斷當(dāng)前的Bean是否有相關(guān)的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 有就創(chuàng)建代理對(duì)象并返回
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
判斷Bean是否需要代理
是否需要代理的的依據(jù)就是wrapIfNecessary方法中的getAdvicesAndAdvisorsForBean(),通過檢查本bean是否有關(guān)聯(lián)切面來判斷是否需要代理。判斷切面關(guān)聯(lián)的邏輯:
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
重點(diǎn)在于查找和當(dāng)前bean相關(guān)的aspect,如何查找的?
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 內(nèi)部邏輯是檢查所有注冊(cè)的Aspect bean,取到其中的Advice定義,封裝到Advisor中(InstantiationModelAwarePointcutAdvisor)
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
findCandidateAdvisors返回所有備選的advisor,下一步進(jìn)行篩選:findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName),最后進(jìn)行其他處理,返回合格的advisor,繼續(xù)下一步的代理創(chuàng)建。
生成代理
代理對(duì)象的生成入口Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));,詳細(xì)生成過程是通過ProxyFactory工廠對(duì)象生成。
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
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()) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
具體的生成策略有兩種:JdkDynamicAopProxy和ObjenesisCglibAopProxy,就是前述的兩種動(dòng)態(tài)代理方式。
- cglib
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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
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);
}
}
- jdk
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}