前言
在上篇文章 中已经获取到了
bean
的对应增强器,之后,就可以创建对应的代理了,
Spring AOP
底层使用的是
JDK 动态代理
和
CGLIB 的代理
,在什么情况下使用
JDK动态代理
,什么时候使用
CGLIB 代理
呢,下面通过源码来看一下.
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//......
// 获取的增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//............
return bean;
}
创建代理 createProxy
protected Object createProxy(Class? beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
// ....
ProxyFactory proxyFactory = new ProxyFactory();
//复制当前类的一些属性
proxyFactory.copyFrom(this);
// 如果在配置文件中配置的aop标签的属性proxy-target-class为false,
if (!proxyFactory.isProxyTargetClass()) {
// 是否需要代理当前类而不是代理接口,根据preserveTargetClass属性来判断Boolean.TRUE.equals(bd.getAttribute("preserveTargetClass")
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 如果代理的是接口,则添加代理接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 对增强器进行包装,有些增强是通过拦截器等方式来实现的,所以这里统一封装为 Advisor 进行处理
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 加入增强器
proxyFactory.addAdvisors(advisors);
// 设置要代理的类
proxyFactory.setTargetSource(targetSource);
// 用户自定义代理
customizeProxyFactory(proxyFactory);
// 该属性用来控制代理工厂被配置以后,是否还允许修改通知,默认为false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
// 添加接口代理
protected void evaluateProxyInterfaces(Class? beanClass, ProxyFactory proxyFactory) {
Class?[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
//....
if (hasReasonableProxyInterface) {
for (Class? ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
proxyFactory.setProxyTargetClass(true);
}
}
封装增强,在Spring中,有些增强是通过拦截器来实现的,所以这里统一封装为 Advisor 进行处理,对应方法
buildAdvisors()
:
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
//解析所有的 InterceptorName
Advisor[] commonInterceptors = resolveInterceptorNames();
ListObject allInterceptors = new ArrayList();
if (specificInterceptors != null) {
// 添加参数传进来的,即我们自定义的增强
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length 0) {
// 添加拦截器
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
//把拦截器包装为Advisor
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i allInterceptors.size(); i++) {
// wrap包装
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
//wrap包装
// 仅仅对 Advisor 和 Advice进行包装
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 如果本来就是 Advisor,则直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 类型不正确,异常
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// MethodInterceptor 类型使用 DefaultPointcutAdvisor 封装
return new DefaultPointcutAdvisor(advice);
}
// 如果存在 Advisor 的适配器,也需要包装
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
创建代理getProxy
return proxyFactory.getProxy(getProxyClassLoader());
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy():
在这里会判断代理创建的方式,是使用 JDK 的动态代理还是 CGLIB 的代理。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//这里初步判断代理的创建方式,如果不满足则直接使用 JDK 动态代理,如果满足条件,则进一步在判断是否使用 JKD 动态代理还是 CGLIB 代理
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class? targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("......");
}
// 如果代理的是接口或者设置代理的类就是当前类,则使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用 CGLIB 代理
return new ObjenesisCglibAopProxy(config);
}
// 条件不满足CGBLIB的方式直接使用JDK动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
这里的 if 条件有三个:
config.isProxyTargetClass()
: 在 中了解到,我们可以强制 Spring 完全使用 CGLIB 进行代理,只要在配置文件配置
proxy-target-class
属性为true即可,如:
aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/
,如果配置个该属性,则会使用 CGLIB 来创建代理
如果这三个条件有一个满足,则会再进一次判断,需要代理的类是否是接口或者是否设置的就是代理当前类,如果是,则还是会使用 JDK 动态代理,否则的话才会使用 CGLIB 代理。
1.如果代理类实现了接口,则Spring默认使用 JDK 动态代理,但可以设置强制使用 CGLIB 代理 2.JDK 动态代理只能代理接口而不能代理类 3.CGLIB 代理类,通过继承的方式,为目标类生成子类,并重写方法来实现代理,它不能代理final的类或方法 4.关于 JDK 动态代理和 CGLIB 代理的使用方式可以参考
接下来看下 JDK 动态代理和 CGLIB 代理的创建过程:
JDK 动态代理
return new JdkDynamicAopProxy(config);
// JdkDynamicAopProxy.java
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
this.advised = config;
}
通过 JDK 动态代理来获取代理的方法
getProxy()
:
public Object getProxy(ClassLoader classLoader) {
// 获取代理类的接口
Class?[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 处理 equals , hashcode 方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看到,
Spring
使用 JDK 创建代理和我们使用的 JDK 来创建代理是没有区别的,都是使用
Proxy.newProxyInstance
的方式来创建;我们知道 JDK 动态代理有个
invoke
方法,用来执行目标方法,而
JdkDynamicAopProxy
实现了
InvocationHandler
接口,所有它也会重写该方法,在该方法中植入增强:
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 {
// 如果接口没有定义 equals 方法且当前方法是 equals 方法,则不会增强,直接返回
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 如果接口没有定义 hashCode方法且当前方法是 hashCode方法,则不会增强,直接返回
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 如果方法所在的类和Advised是同一个类或者是父类子类关系,则直接执行
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 返回值
Object retVal;
// 这里对应的是expose-proxy属性的应用,把代理暴露处理
// 目标方法内部的自我调用将无法实施切面中的增强,所以在这里需要把代理暴露出去
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class? targetClass = (target != null ? target.getClass() : null);
// 获取该方法的拦截器
ListObject chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//如果方法的拦截器为空,则直接执行目标方法,避免创建 MethodInvocation 对象
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 执行目标方法:method.invoke(target, args)
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 把所有的拦截器封装在ReflectiveMethodInvocation中,以便于链式调用
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
}
// ..........
return retVal;
}
finally {
// .
}
}
在执行拦截器方法
proceed
中执行增强方法,比如前置增强在方法之前执行,后置增强在方法之后执行,
proceed
方法如下:
public Object proceed() throws Throwable {
//当执行完所有增强方法后执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// method.invoke(target, args)
return invokeJoinpoint();
}
// 获取下一个要执行的拦截器
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 动态匹配
InterceptorAndDynamicMethodMatcher dm = interceptorOrInterceptionAdvice;
Class? targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 如果能够匹配,则执行拦截器的方法,
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 比如 @After @Before 对应的增强器(拦截器)的方法
// 比如 @After 对应的增强器 AspectJAfterAdvice 的invoke方法为:MethodInvocation.proceed();
return dm.interceptor.invoke(this);
}
else {
// 如果动态匹配失败,则跳过该拦截器,执行下一个拦截器
return proceed();
}
}
else {
// 普通拦截器,直接调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
在该方法中完成了增强的植入,主要逻辑就是,每个方法都会有一个拦截器链,在 AOP 中我们称之为增强,然后循环执行每个拦截器链,当执行完所有的拦截器后,才会执行目标方法。比如
@After
对应的增强器
AspectJAfterAdvice
,
@Around
对应的增强器
AspectJAroundAdvice
等。
以上就是 Spring 通过 JDK 动态代理来实现 AOP 的一个过程。
CGLIB 代理
ObjenesisCglibAopProxy
继承于
CglibAopProxy
return new ObjenesisCglibAopProxy(config)
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
CglibAopProxy
的
getProxy
方法如下:
public Object getProxy(ClassLoader classLoader) {
// 代理的目标类
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);
}
}
// 创建并配置 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();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//生成代理类和创建代理
return createProxyClassAndInstance(enhancer, callbacks);
}
// 生成代理类和创建代理
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
从上述的方法可知,Sping 使用 CGLIB 来创建代理类和代理对象和我们使用的一样,都是使用
Enhancer.create()
来创建,这里主要的是设置拦截器,通过
getCallbacks ()
方法来实现的,如下:
private Callback[] getCallbacks(Class? rootClass) throws Exception {
//expose-proxy 属性
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 将拦截器封装在 DynamicAdvisedInterceptor 中
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
//暴露代理
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()));
}
// 将拦截器 aopInterceptor 进入到 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)
};
// ..............
return callbacks;
}
我们知道使用
CGLIB
来实现代理功能的时候,当代理执行的时候,会调用
intercept
方法,和
JKD 动态代理
的
invoke
方法类似;Spring 中
CGLIB
的
intercept
方法如下,该方法在
DynamicAdvisedInterceptor
中,从上面的代理知道,使用它来封装拦截器,它是
CglibAopProxy
的一个子类:
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy){
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
// 目标类
TargetSource targetSource = this.advised.getTargetSource();
// 处理 expose-proxy 属性,暴露代理
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class? targetClass = (target != null ? target.getClass() : null);
// 获取拦截器链
ListObject 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 {
//封装拦截器链并执行
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 处理返回值类型
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
// .....................
}
CGLIB 使用
CglibMethodInvocation
来封装拦截器链,它是
CglibAopProxy
的一个内部类:
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
@Nullable
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object proxy, Object target, Method method,Object[] arguments, Class? targetClass, ListObject interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}
// proceed 方法会调用该方法来执行
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invokeJoinpoint();
}
}
}
当调用
proceed
方法时,和 JDK 的处理是一样的,只不过当执行完所有的拦截器后,执行目标方法调用的是
CglibMethodInvocation
的
invokeJoinpoint
来执行而已;
因为
CglibMethodInvocation
继承于
ReflectiveMethodInvocation
,而 JDK 使用的就是
ReflectiveMethodInvocation
来执行的,
ReflectiveMethodInvocation
的
invokeJoinpoint
方法为 :
method.invoke(target, args)
以上就是 Spring 使用 JDK 动态代理和 CGLIB 代理来实现 AOP 的原理。
原文始发于微信公众号(Java技术大杂烩):