前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义

Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义

作者头像
大忽悠爱学习
发布2022-05-10 16:41:56
1.2K0
发布2022-05-10 16:41:56
举报
文章被收录于专栏:c++与qt学习

Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义


引子

回看生成DefaultAopProxyFactory的createAopProxy方法来生成代理类

代码语言:javascript
复制
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {


	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(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() || Proxy.isProxyClass(targetClass)) {
			//采用JdkDynamicAopProxy生成jdk动态代理对象
				return new JdkDynamicAopProxy(config);
			}
			//采用ObjenesisCglibAopProxy生成cglib动态代理对象
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

	/**
	 * Determine whether the supplied {@link AdvisedSupport} has only the
	 * {@link org.springframework.aop.SpringProxy} interface specified
	 * (or no proxy interfaces specified at all).
	 */
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

Spring所有的代理AopProxy的创建最后都是ProxyCreatorSupport#createAopProxy这个方法

代码语言:javascript
复制
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//getAopProxyFactory拿到的就是DefaultAopProxyFactory 
		//createAopProxy调用的就是DefaultAopProxyFactory类里面的方法
		return getAopProxyFactory().createAopProxy(this);
	}

显然它又是调用了AopProxyFactory#createAopProxy方法,它的唯一实现为DefaultAopProxyFactory。

它做了一个简单的逻辑判断:若实现类接口,使用JdkDynamicAopProxy最终去创建,否则交给ObjenesisCglibAopProxy。

最终拿到AopProxy后,调用AopProxy#getProxy()就会拿到这个代理对象,从而进行相应的工作了。

我们基本有一共共识就是:默认情况下,若我们实现了接口,就实用JDK动态代理,若没有就实用CGLIB。那么就下来,就具体看看关乎到代理对象的创建、执行的一个具体过程原理


动态代理和静态代理回顾

AOP(Aspect Orient Programming),一般称为面向切面编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。

AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。静态代理是编译期实现,动态代理是运行期实现,可想而知前者拥有更好的性能。

静态代理:

静态代理是编译阶段生成AOP代理类,也就是说生成的字节码就织入了增强后的AOP对象;(并不会创建出多余的对象)

实现方式:

  • 包装器模式:持有目标对象的引用,然后实际上是调用目标对象的方法。 这种方式也可称为代理模式,但是有明显的缺点(比如一般都需要实现同一个接口,且它是以编码的方式去实现的,侵入性高)
  • AspectJ静态代理方式:非常非常强大。Aspectj并不是动态的在运行时生成代理类,而是在编译的时候就植入代码到class文件。由于是静态织入的,所以性能相对来说比较好。Aspectj不受类的特殊限制,不管方法是private、或者static、或者final的,都可以代理,Aspectj不会代理除了限定方法之外任何其他诸如toString(),clone()等方法,唯一缺点就是必须有AspectJ自己的编译器的支持,所以其实很少使用 Spring也是提供了相关类支持的,比如:LoadTimeWeaverAwareProcessor

基于AspectJ的静态代理方式非常强大,但是它依赖于它自己的编译器。并且还有自己的个性化语言,使用起来不够方便,因此其实还是使用得较少的。主要还是以动态代理为主~~~

动态代理:

动态代理则不会修改字节码,而是在内存中临时生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法

这在我们平时使用中得到了大量的使用,因为使用简单并且还非常灵活,下面就重点介绍。


AopProxy:Aop代理接口

它是一个AOP代理的抽象接口。提供了两个方法,让我们可以获取对应 配置的AOP对象的代理:

代码语言:javascript
复制
public interface AopProxy {
	//Create a new proxy object. Uses the AopProxy's default class loader  ClassUtils.getDefaultClassLoader()
	Object getProxy();
	Object getProxy(@Nullable ClassLoader classLoader);
}

它的继承关系也很简单,就是接下来我们要说的那几个


JdkDynamicAopProxy—jdk生成动态代理对象

代码语言:javascript
复制
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 5531744639992436476L;

	/** We use a static Log to avoid serialization issues. */
	private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);

	/**当前代理对象相关配置信息保存 **/
	private final AdvisedSupport advised;
    //当前代理对象需要代理的接口
	private final Class<?>[] proxiedInterfaces;

	/**
	 * Is the {@link #equals} method defined on the proxied interfaces?
	 */
	private boolean equalsDefined;

	/**
	 * Is the {@link #hashCode} method defined on the proxied interfaces?
	 */
	private boolean hashCodeDefined;

	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		//completeProxiedInterfaces方法会获得当前类需要代理的接口
		//并且额外还会让代理对象实现两个接口,但是因为第二个参数为true
		//因此一共会让代理对象再额外实现三个接口:SpringProxy,Advised和DecoratingProxy
		this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
	}


	@Override
	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		//获得代理对象的方法十分的简单,就是最原始的jdk生成动态代理的方法
		//但是此时传入的拦截器方法为当前类,因为其实现了InvocationHandler接口
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

	/**
	 * Finds any {@link #equals} or {@link #hashCode} method that may be defined
	 * on the supplied set of interfaces.
	 * @param proxiedInterfaces the interfaces to introspect
	 */
	private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
		for (Class<?> proxiedInterface : proxiedInterfaces) {
			Method[] methods = proxiedInterface.getDeclaredMethods();
			for (Method method : methods) {
				if (AopUtils.isEqualsMethod(method)) {
					this.equalsDefined = true;
				}
				if (AopUtils.isHashCodeMethod(method)) {
					this.hashCodeDefined = true;
				}
				if (this.equalsDefined && this.hashCodeDefined) {
					return;
				}
			}
		}
	}


	/**
调用链的执行
	 */
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;
        //拿到包装了目标对象的TargetSource 
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
             //“通常情况”Spring AOP不会对equals、hashCode方法进行拦截增强,所以此处做了处理
			// equalsDefined为false(表示自己没有定义过equals方法)  那就交给代理去比较
			// hashCode同理,只要你自己没有实现过此方法,那就交给代理吧
			// 需要注意的是:这里统一指的是,如果接口上有此方法,但是你自己并没有实现equals和hashCode方法,那就走AOP这里的实现
			// 如国接口上没有定义此方法,只是实现类里自己@Override了HashCode,那是无效的,就是普通执行吧
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			//如果当前方法属于DecoratingProxy接口中getDecoratedClass方法
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				//那么直接通过分析代理配置信息返回目标对象的类型
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			//opaque默认为false,表示代理对象会继承Advised接口
			else if (!this.advised.opaque && 
			        //当前方法属于某个接口中的方法
			        method.getDeclaringClass().isInterface() &&
					//当前接口是Advised或者其子类
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				//那么当前用户是想将代理对象强制转换为advised接口后,调用该接口中某个方法
				//那么这里转而调用内部维护的代理类配置信息的method方法
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
           
             //是否暴露代理对象,默认false可配置为true,如果暴露就意味着允许在线程内共享代理对象,
			//注意这是在线程内,也就是说同一线程的任意地方都能通过AopContext获取该代理对象,这应该算是比较高级一点的用法了。
			// 这里缓存一份代理对象在oldProxy里~~~后面有用
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				//设置代理对象到当前线程
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			//拿到目标对象
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			//对代理类配置信息中的Advisors集合进行筛选,找出可以应用到当前类和当前类的method方法上的增强器
			//然后把这些增强器适配为methodInterceptor后加入集合中统一返回
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 
			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			//当前方法没有适合的拦截器链生成,那么直接反射执行方法即可
			if (chain.isEmpty()) {
				// 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
			//当前方法有相关联的拦截器链集合
				// We need to create a method invocation...
				//构造拦截器链
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				//拦截器链开始执行
				//ReflectiveMethodInvocation的proceed方法,不清楚的可以翻看我之前的文章
				//该方法最后返回方法的执行结果
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			//获取方法的返回值
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			//如果方法实际返回值不为null,但是获得的返回结果为null,那么抛出异常
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				//使用targetSource绑定的target对象,这样一来,targetSource可以完成重用111
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// 把老的代理对象重新set进去~~~
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}


	/**
	 * Equality means interfaces, advisors and TargetSource are equal.
	 * <p>The compared object may be a JdkDynamicAopProxy instance itself
	 * or a dynamic proxy wrapping a JdkDynamicAopProxy instance.
	 */
	@Override
	public boolean equals(@Nullable Object other) {
		if (other == this) {
			return true;
		}
		if (other == null) {
			return false;
		}

		JdkDynamicAopProxy otherProxy;
		if (other instanceof JdkDynamicAopProxy) {
			otherProxy = (JdkDynamicAopProxy) other;
		}
		else if (Proxy.isProxyClass(other.getClass())) {
			InvocationHandler ih = Proxy.getInvocationHandler(other);
			if (!(ih instanceof JdkDynamicAopProxy)) {
				return false;
			}
			otherProxy = (JdkDynamicAopProxy) ih;
		}
		else {
			// Not a valid comparison...
			return false;
		}

		// If we get here, otherProxy is the other AopProxy.
		return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised);
	}

	/**
	 * Proxy uses the hash code of the TargetSource.
	 */
	@Override
	public int hashCode() {
		return JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
	}

}

该类的设计思路和我们平时自己使用jdk动态代理思路一致,大致有以下几步:

  • 通过构造函数传入的AdvisedSupport代理配置信息,分析得到当前代理类需要实现的接口数组
  • 获取代理对象的时候,就和平时一样,通过newProxyInstance完成即可,但是InvocationHandler传入的是JdkDynamicAopProxy自身,因为他实现了该接口
  • 当目标方法被调用,会触发InvocationHandler的invoke方法,在该方法内JdkDynamicAopProxy会首先获取拦截器链,然后执行拦截器链,获取最终执行结果,然后返回

对jdk动态代理底层原理不清楚的,建议看一下本文

还有一点需要注意,就是代理类会额外实现SpringProxy,Advised和DecoratingProxy三个接口,代码体现在下面这行:

代码语言:javascript
复制
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

AopProxyUtils不懂的,看本文


CglibAopProxy----cglib生成动态代理对象

要想搞懂CglibAopProxy的组织思路,callbackFilter必须要了解,建议大家先看一下:

cglib的callbackFilter介绍

代码语言:javascript
复制
@SuppressWarnings("serial")
class CglibAopProxy implements AopProxy, Serializable {

	// Constants for CGLIB callback array indices
	//这里的序号用于callBackFilter中,选择某个方法交给某个callback时,会用到
	private static final int AOP_PROXY = 0;
	private static final int INVOKE_TARGET = 1;
	private static final int NO_OVERRIDE = 2;
	private static final int DISPATCH_TARGET = 3;
	private static final int DISPATCH_ADVISED = 4;
	private static final int INVOKE_EQUALS = 5;
	private static final int INVOKE_HASHCODE = 6;


	/** Logger available to subclasses; static to optimize serialization. */
	protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);

	/** Keeps track of the Classes that we have validated for final methods. */
	//对已经校验过的类进行缓存处理
	private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();


	/**  代理配置类信息 **/
	protected final AdvisedSupport advised;
   
   //因为是采用继承方式实现的代理,因此需要考虑父类的构造函数
	@Nullable
	protected Object[] constructorArgs;
   //构造函数参类型
	@Nullable
	protected Class<?>[] constructorArgTypes;
  
	/** 简单包装了一下AdvisedSupport */
	private final transient AdvisedDispatcher advisedDispatcher;

	private transient Map<Method, Integer> fixedInterceptorMap = Collections.emptyMap();

	private transient int fixedInterceptorOffset;

	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}
    
    //设置构造函数相关信息
	public void setConstructorArguments(@Nullable Object[] constructorArgs, @Nullable Class<?>[] constructorArgTypes) {
		if (constructorArgs == null || constructorArgTypes == null) {
			throw new IllegalArgumentException("Both 'constructorArgs' and 'constructorArgTypes' need to be specified");
		}
		if (constructorArgs.length != constructorArgTypes.length) {
			throw new IllegalArgumentException("Number of 'constructorArgs' (" + constructorArgs.length +
					") must match number of 'constructorArgTypes' (" + constructorArgTypes.length + ")");
		}
		this.constructorArgs = constructorArgs;
		this.constructorArgTypes = constructorArgTypes;
	}


	@Override
	public Object getProxy() {
		return getProxy(null);
	}

//获取代理对象,重点方法重点讲解***
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
		//拿到目标对象类型
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
       //因为采用继承方式实现代理,这里拿到的是SuperClass,即目标类
			Class<?> proxySuperClass = rootClass;
			//如果目标类已经是cglib代理类了
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				//拿到当前cglib代理类的父类
				proxySuperClass = rootClass.getSuperclass();
				//还要拿到当前cglib代理类实现的接口
				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...
			//创建cglib增强器
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				//检查当前类是否可以进行缓存
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			//设置父类---即从代理配置中拿到的目标类
			enhancer.setSuperclass(proxySuperClass);
			//设置代理类需要实现的接口---completeProxiedInterfaces
			//如果了解completeProxiedInterfaces方法实现的小伙伴应该知道,单个参数的completeProxiedInterfaces方法
			//第二个参数decoratingProxy为false,表示代理类不会实现DecoratingProxy接口,只会额外实现Advised和SpringProxy接口
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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(
            //CallbackFilte可以明确表明,被代理的类中不同的方法,被哪个拦截器所拦截
            //通过返回一个下标表示,该下标对应callbacks数组中对应位置元素
            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 | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
	//设置是否拦截从代理的构造函数中调用的方法。默认值是true。拦截的方法将调用代理基类的方法(如果存在)。
	//spring的处理,这里可以看出,如果在代理对象的构造函数中调用代理对象中某个方法,该方法是不糊被拦截的
		enhancer.setInterceptDuringConstruction(false);
	//设置回调接口
		enhancer.setCallbacks(callbacks);
		return (this.constructorArgs != null && this.constructorArgTypes != null ?
				//如果存在构造函数,那么就走有参构造创建
				enhancer.create(this.constructorArgTypes, this.constructorArgs) :
				//否则走无参构造创建
				enhancer.create());
	}

	/**
	 * Creates the CGLIB {@link Enhancer}. Subclasses may wish to override this to return a custom
	 * {@link Enhancer} implementation.
	 */
	protected Enhancer createEnhancer() {
		return new Enhancer();
	}

	/**
	 * Checks to see whether the supplied Class has already been validated and
	 * validates it if not.
	 */
	private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
		if (logger.isWarnEnabled()) {
			synchronized (validatedClasses) {
			//当前目标对象类是否已经被校验过
				if (!validatedClasses.containsKey(proxySuperClass)) {
					//没有校验过,就进行校验,然后校验完毕后,加入缓存中
					doValidateClass(proxySuperClass, proxyClassLoader,
							ClassUtils.getAllInterfacesForClassAsSet(proxySuperClass));
					validatedClasses.put(proxySuperClass, Boolean.TRUE);
				}
			}
		}
	}

	/**
	 * Checks for final methods on the given {@code Class}, as well as package-visible
	 * methods across ClassLoaders, and writes warnings to the log for each one found.
	 * 主要是日志记录,对final和私有方法无法被代理,进行日志提醒
	 */
	private void doValidateClass(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader, Set<Class<?>> ifcs) {
	     //如果目标类是Object,就不进行校验了,说明 
		if (proxySuperClass != Object.class) {
		   //获取目标对象内部的所有方法,包括私有
			Method[] methods = proxySuperClass.getDeclaredMethods();
			for (Method method : methods) {
				int mod = method.getModifiers();
				if (!Modifier.isStatic(mod) && !Modifier.isPrivate(mod)) {
					//进入这里说明当前方法是非静态和非私有的方法
					if (Modifier.isFinal(mod)) {
						//但是如果该方法是final方法,那么cglib无法对当前方法完成重写,然后实施拦截的操作
						//这里只是日志提醒,但是不会抛出异常
						if (logger.isInfoEnabled() && implementsInterface(method, ifcs)) {
							logger.info("Unable to proxy interface-implementing method [" + method + "] because " +
									"it is marked as final: Consider using interface-based JDK proxies instead!");
						}
						if (logger.isDebugEnabled()) {
							logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
									"Calls to this method will NOT be routed to the target instance and " +
									"might lead to NPEs against uninitialized fields in the proxy instance.");
						}
					}
					//如果当前方法是私有的,那么父类的私有方法对子类而言是不可见的,因此也无法完成重写,进而实施拦截操作
					else if (logger.isDebugEnabled() && !Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
							proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
						logger.debug("Method [" + method + "] is package-visible across different ClassLoaders " +
								"and cannot get proxied via CGLIB: Declare this method as public or protected " +
								"if you need to support invocations through the proxy.");
					}
				}
			}
			//如果当前目标对象还有父类,那么就对其父类进行递归校验,知道父类为底层Object为止
			doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader, ifcs);
		}
	}

//返回拦截器链***比较重要
//讲解这个方法前,我们必须先明白一点,cglib可以向enchaner中加入不只一个callback
//然后可以通过callbackfilter来决定在方法被拦截后,先走到callbackfilter,通过其accept方法返回一个整数索引,来决定具体交给哪一个callback进行处理
	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		//exposeProxy属性决定是否需要将当前对象暴露到AopContext中去
		boolean exposeProxy = this.advised.isExposeProxy();
		//是否需要冻结配置
		boolean isFrozen = this.advised.isFrozen();
		//是否每次TargetSource都返回相同类型的目标对象,默认为SingletonTargetSource,这里为true
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		//通用 AOP 回调。当目标是动态的或代理未冻结时使用。---该类是当前类的内部类
		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.
		//targetInterceptor是直接会触发目标对象方法的拦截器,在某个方法没有关联的拦截器链时,会通过accpet方法,直接返回该拦截器在callback中的固定索引
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (
		//默认为	SingletonTargetSource,为true
		//isStatic为false的话,那么每次TargetSource每次会返回不同的target对象,因此只能往拦截器中放入targetSource,而非目标对象
		//含有Exposed的字符串,说明该拦截器执行拦截的过程中,会将代理对象放入aopcontext中
		//Static个dynamic的区别在于是否每次都需要重新从targetSource获取一次target
        isStatic ?
        //两个都是当前类的内部类,下面会讲到
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					//DynamicUnadvisedExposedInterceptor不会将目标对象放入aopcontext中
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
		//不会将对象放入aopcontext中
			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).
		//当目标方法是在advised上调用的时候,会返回该回调
		Callback targetDispatcher = (
//isStatic为false的话,那么每次TargetSource每次会返回不同的target对象,因此只能往拦截器中放入targetSource,而非目标对象
isStatic ?
				//保存target目标对象
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : 
      //空实现
      new SerializableNoOp());

//主要的回调接口集合--callback的索引很重要
		Callback[] mainCallbacks = new Callback[] {
		//主要的拦截器链
				aopInterceptor,  // for normal advice
				//一般都是StaticUnadvisedExposedInterceptor
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				//拿到目标对象和代理配置对象
				targetDispatcher, this.advisedDispatcher,
				//equals和hashcode拦截处理
				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 optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		//如果目标是静态的并且通知链被冻结,
		//那么我们可以通过使用该方法的固定链将 AOP 调用直接发送到目标来进行一些优化。
		if (isStatic && isFrozen) {
		//拿到目标类中每个方法关联的拦截器链后,放入map集合,形成方法--->拦截器链的映射关系
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			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);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			//callbacks=mainCallbacks+fixedCallbacks
			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;
	}



	/**
    对被代理方法执行后的返回值进行处理
	 */
	@Nullable
	private static Object processReturnType(
			Object proxy, @Nullable Object target, Method method, @Nullable Object returnValue) {

		// Massage return value if necessary
		if (returnValue != null && returnValue == target &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this". Note that we can't help
			// if the target sets a reference to itself in another returned object.
			returnValue = proxy;
		}
		Class<?> returnType = method.getReturnType();
		if (returnValue == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return returnValue;
	}

	/**
	 * Method interceptor used for static targets with no advice chain. The call
	 * is passed directly back to the target. Used when the proxy needs to be
	 * exposed and it can't be determined that the method won't return
	 */
	private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {

		@Nullable
		private final Object target;

		public StaticUnadvisedInterceptor(@Nullable Object target) {
			this.target = target;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 
		   //直接调用目标方法
			Object retVal = methodProxy.invoke(this.target, args);
			//处理返回值
			return processReturnType(proxy, this.target, method, retVal);
		}
	}


	/**
	 * Method interceptor used for static targets with no advice chain, when the
	 * proxy is to be exposed.
	 */
	private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {

		@Nullable
		private final Object target;

		public StaticUnadvisedExposedInterceptor(@Nullable Object target) {
			this.target = target;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
		  //和上面相比,多了一步,将代理对象放入aopcontext中
			Object oldProxy = null;
			try {
				oldProxy = AopContext.setCurrentProxy(proxy);
				//目标方法执行
				Object retVal = methodProxy.invoke(this.target, args);
				return processReturnType(proxy, this.target, method, retVal);
			}
			finally {
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}


	/**
	 * Interceptor used to invoke a dynamic target without creating a method
	 * invocation or evaluating an advice chain. (We know there was no advice
	 * for this method.)
	 */
	private static class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {

		private final TargetSource targetSource;

		public DynamicUnadvisedInterceptor(TargetSource targetSource) {
			this.targetSource = targetSource;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		//Dynamic说明targetSource每次返回的target都是不同的,因此每次都需要去重新获取一遍target
			Object target = this.targetSource.getTarget();
			try {
				Object retVal = methodProxy.invoke(target, args);
				return processReturnType(proxy, target, method, retVal);
			}
			finally {
				if (target != null) {
					this.targetSource.releaseTarget(target);
				}
			}
		}
	}


	/**
	 * Interceptor for unadvised dynamic targets when the proxy needs exposing.
	 */
	private static class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {

		private final TargetSource targetSource;

		public DynamicUnadvisedExposedInterceptor(TargetSource targetSource) {
			this.targetSource = targetSource;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		    //代理放入aopcontext中
			Object oldProxy = null;
			Object target = this.targetSource.getTarget();
			try {
				oldProxy = AopContext.setCurrentProxy(proxy);
				Object retVal = methodProxy.invoke(target, args);
				return processReturnType(proxy, target, method, retVal);
			}
			finally {
				AopContext.setCurrentProxy(oldProxy);
				if (target != null) {
					this.targetSource.releaseTarget(target);
				}
			}
		}
	}


	/**
	 * Dispatcher for a static target. Dispatcher is much faster than
	 * interceptor. This will be used whenever it can be determined that a
	 * method definitely does not return "this"
	 */
	private static class StaticDispatcher implements Dispatcher, Serializable {

		@Nullable
		private final Object target;

		public StaticDispatcher(@Nullable Object target) {
			this.target = target;
		}

		@Override
		@Nullable
		public Object loadObject() {
			return this.target;
		}
	}


	/**
	 * Dispatcher for any methods declared on the Advised class.
	 */
	private static class AdvisedDispatcher implements Dispatcher, Serializable {

		private final AdvisedSupport advised;

		public AdvisedDispatcher(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		public Object loadObject() {
			return this.advised;
		}
	}


	/**
	 * Dispatcher for the {@code equals} method.
	 * Ensures that the method call is always handled by this class.
	 */
	private static class EqualsInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public EqualsInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
			Object other = args[0];
			if (proxy == other) {
				return true;
			}
			if (other instanceof Factory) {
				Callback callback = ((Factory) other).getCallback(INVOKE_EQUALS);
				if (!(callback instanceof EqualsInterceptor)) {
					return false;
				}
				AdvisedSupport otherAdvised = ((EqualsInterceptor) callback).advised;
				return AopProxyUtils.equalsInProxy(this.advised, otherAdvised);
			}
			else {
				return false;
			}
		}
	}


	/**
	 * Dispatcher for the {@code hashCode} method.
	 * Ensures that the method call is always handled by this class.
	 */
	private static class HashCodeInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public HashCodeInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
			return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
		}
	}


	/**
	 * Interceptor used specifically for advised methods on a frozen, static proxy.
	 * 拦截器专门用于冻结的静态代理上的建议方法。
	 */
	private static class FixedChainStaticTargetInterceptor implements MethodInterceptor, Serializable {

		private final List<Object> adviceChain;

		@Nullable
		private final Object target;

		@Nullable
		private final Class<?> targetClass;

		public FixedChainStaticTargetInterceptor(
				List<Object> adviceChain, @Nullable Object target, @Nullable Class<?> targetClass) {

			this.adviceChain = adviceChain;
			this.target = target;
			this.targetClass = targetClass;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		//构造然后执行拦截器链
			MethodInvocation invocation = new CglibMethodInvocation(
					proxy, this.target, method, args, this.targetClass, this.adviceChain, methodProxy);
			// If we get here, we need to create a MethodInvocation.
			Object retVal = invocation.proceed();
			retVal = processReturnType(proxy, this.target, method, retVal);
			return retVal;
		}
	}


	/**
	 * General purpose AOP callback. Used when the target is dynamic or when the
	 * proxy is not frozen.
	 * 重点拦截器:通用 AOP 回调。当目标是动态的或代理未冻结时使用。
	 */
	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
			//如果exposeProxy为true,那么就把代理对象放入aopcontext中
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				//拿到当前方法关联的拦截器链
				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 && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other ||
					(other instanceof DynamicAdvisedInterceptor &&
							this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
		}

		/**
		 * CGLIB uses this to drive proxy creation.
		 */
		@Override
		public int hashCode() {
			return this.advised.hashCode();
		}
	}


	/**
	 * Implementation of AOP Alliance MethodInvocation used by this AOP proxy.
	 */
	private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

		@Nullable
		private final MethodProxy methodProxy;

		public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
				Object[] arguments, @Nullable Class<?> targetClass,
				List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

			super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);

			// Only use method proxy for public methods not derived from java.lang.Object
			this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
					method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
					!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
					methodProxy : null);
		}

		@Override
		@Nullable
		public Object proceed() throws Throwable {
			try {
			//所有拦截器执行完毕后,执行invokeJoinpoint方法
				return super.proceed();
			}
			catch (RuntimeException ex) {
				throw ex;
			}
			catch (Exception ex) {
				if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
						KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
					// Propagate original exception if declared on the target method
					// (with callers expecting it). Always propagate it for Kotlin code
					// since checked exceptions do not have to be explicitly declared there.
					throw ex;
				}
				else {
					// Checked exception thrown in the interceptor but not declared on the
					// target method signature -> apply an UndeclaredThrowableException,
					// aligned with standard JDK dynamic proxy behavior.
					throw new UndeclaredThrowableException(ex);
				}
			}
		}

		/**
		 * Gives a marginal performance improvement versus using reflection to
		 * invoke the target when invoking public methods.
		 */
		@Override
		protected Object invokeJoinpoint() throws Throwable {
			if (this.methodProxy != null) {
				return this.methodProxy.invoke(this.target, this.arguments);
			}
			else {
				return super.invokeJoinpoint();
			}
		}
	}


	/**
	 * CallbackFilter to assign Callbacks to methods.
	 */
	private static class ProxyCallbackFilter implements CallbackFilter {

		private final AdvisedSupport advised;

		private final Map<Method, Integer> fixedInterceptorMap;

		private final int fixedInterceptorOffset;

		public ProxyCallbackFilter(
				AdvisedSupport advised, Map<Method, Integer> fixedInterceptorMap, int fixedInterceptorOffset) {

			this.advised = advised;
			this.fixedInterceptorMap = fixedInterceptorMap;
			this.fixedInterceptorOffset = fixedInterceptorOffset;
		}
        
        //方法返回值可以决定当前方法教给callbacks数组中哪一个callback进行处理,该方法很重要
        //但是该方法我不太想多讲,大家联系该类最开始给出的几个整型常量和getCallBack方法给出的mainCallBack中固定的callBack组合
        //以及cglib的callBackFilter机制,相信下面这个方法
		@Override
		public int accept(Method method) {
			if (AopUtils.isFinalizeMethod(method)) {
				logger.trace("Found finalize() method - using NO_OVERRIDE");
				return NO_OVERRIDE;
			}
			if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				if (logger.isTraceEnabled()) {
					logger.trace("Method is declared on Advised interface: " + method);
				}
				return DISPATCH_ADVISED;
			}
			// We must always proxy equals, to direct calls to this.
			if (AopUtils.isEqualsMethod(method)) {
				if (logger.isTraceEnabled()) {
					logger.trace("Found 'equals' method: " + method);
				}
				return INVOKE_EQUALS;
			}
			// We must always calculate hashCode based on the proxy.
			if (AopUtils.isHashCodeMethod(method)) {
				if (logger.isTraceEnabled()) {
					logger.trace("Found 'hashCode' method: " + method);
				}
				return INVOKE_HASHCODE;
			}
			Class<?> targetClass = this.advised.getTargetClass();
			// Proxy is not yet available, but that shouldn't matter.
			List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			boolean haveAdvice = !chain.isEmpty();
			boolean exposeProxy = this.advised.isExposeProxy();
			boolean isStatic = this.advised.getTargetSource().isStatic();
			boolean isFrozen = this.advised.isFrozen();
			if (haveAdvice || !isFrozen) {
				// If exposing the proxy, then AOP_PROXY must be used.
				if (exposeProxy) {
					if (logger.isTraceEnabled()) {
						logger.trace("Must expose proxy on advised method: " + method);
					}
					return AOP_PROXY;
				}
				// Check to see if we have fixed interceptor to serve this method.
				// Else use the AOP_PROXY.
				if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Method has advice and optimizations are enabled: " + method);
					}
					// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
					int index = this.fixedInterceptorMap.get(method);
					return (index + this.fixedInterceptorOffset);
				}
				else {
					if (logger.isTraceEnabled()) {
						logger.trace("Unable to apply any optimizations to advised method: " + method);
					}
					return AOP_PROXY;
				}
			}
			else {
				// See if the return type of the method is outside the class hierarchy of the target type.
				// If so we know it never needs to have return type massage and can use a dispatcher.
				// If the proxy is being exposed, then must use the interceptor the correct one is already
				// configured. If the target is not static, then we cannot use a dispatcher because the
				// target needs to be explicitly released after the invocation.
				if (exposeProxy || !isStatic) {
					return INVOKE_TARGET;
				}
				Class<?> returnType = method.getReturnType();
				if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Method return type is assignable from target type and " +
								"may therefore return 'this' - using INVOKE_TARGET: " + method);
					}
					return INVOKE_TARGET;
				}
				else {
					if (logger.isTraceEnabled()) {
						logger.trace("Method return type ensures 'this' cannot be returned - " +
								"using DISPATCH_TARGET: " + method);
					}
					return DISPATCH_TARGET;
				}
			}
		}
....
	}

}

CallBackFilter的accpet方法英文注释如下:


ObjenesisCglibAopProxy—CglibAopProxy子类

ObjenesisCglibAopProxy继承自CglibAopProxy,它只重写了createProxyClassAndInstance方法,createProxyClassAndInstancey是用来创建代理类的

CglibAopProxy中的createProxyClassAndInstance

代码语言:javascript
复制
	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());
	}

ObjenesisCglibAopProxy中的createProxyClassAndInstance

代码语言:javascript
复制
class ObjenesisCglibAopProxy extends CglibAopProxy {

	private static final Log logger = LogFactory.getLog(ObjenesisCglibAopProxy.class);

	private static final SpringObjenesis objenesis = new SpringObjenesis();


	/**
	 * Create a new ObjenesisCglibAopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 */
	public ObjenesisCglibAopProxy(AdvisedSupport config) {
		super(config);
	}


	@Override
	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		Class<?> proxyClass = enhancer.createClass();
		Object proxyInstance = null;

		// 如果为true,那我们就采用objenesis去new一个实例~~~
		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);
			}
		}
// 若果还为null,就再去拿到构造函数(指定参数的)
		if (proxyInstance == null) {
			// Regular instantiation via default constructor...
			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("Unable to instantiate proxy using Objenesis, " +
						"and regular proxy instantiation via default constructor fails as well", ex);
			}
		}

		((Factory) proxyInstance).setCallbacks(callbacks);
		return proxyInstance;
	}

}

Objenesis下面会讲,这里先不着急,一会我讲完Objenesis后,大家再回头看一下这个方法


小结

  • 和JDK的一样,Object的方法,只有toString()会被拦截(执行通知)
  • 生成出来的代理对象,Spring默认都给你实现了接口:SpringProxy、Advised;
  • Cglib和jdk生成动态代理在spring中区别之一在于,cglib生成的代理对象不会实现DecoratingProxy接口
  • cglib和JDK不同的是,比如equals和hashCode等方法根本就不会进入intecept方法,而是在getCallbacks()那里就给特殊处理掉了

Objenesis:另一种实例化对象的方式

它专门用来创建对象,即使你没有空的构造函数,都木有问题~~ 可谓非常的强大

它不使用构造方法创建Java对象,所以即使你有空的构造方法,也是不会执行的。

Objenesis是一个Java的库,主要用来创建特定的对象。

由于不是所有的类都有无参构造器又或者类构造器是private,在这样的情况下,如果我们还想实例化对象,class.newInstance是无法满足的。


使用ObjenesisStd

代码语言:javascript
复制
public class MainTest {

    public static void main(String[] args) throws Exception {
        Objenesis objenesis = new ObjenesisStd();
        // 它竟然创建成功了
        MyDemo myDemo = objenesis.newInstance(MyDemo.class);
        System.out.println(myDemo); //com.fsx.maintest.MyDemo@1f32e575
        System.out.println(myDemo.code); //null  特别注意:这里是null,而不是10

        // 若直接这样创建 就报错 java.lang.InstantiationException: com.fsx.maintest.MyDemo
        System.out.println(MyDemo.class.newInstance());
    }
}

class MyDemo {
    public String code = "10";

    public MyDemo(String code) {
        this.code = code;
    }
}

使用ObjectInstantiator

代码语言:javascript
复制
    public static void main(String[] args) throws Exception {
        Objenesis objenesis = new ObjenesisStd();
        // 相当于生成了一个实例创建的工厂,接下来就可以很方便得创建实例了
        // 如果你要创建多个实例,建议这么来创建
        ObjectInstantiator<MyDemo> instantiator = objenesis.getInstantiatorOf(MyDemo.class);

        MyDemo myDemo1 = instantiator.newInstance();
        MyDemo myDemo2 = instantiator.newInstance();
        System.out.println(myDemo1);
        System.out.println(myDemo1.code); //null
        System.out.println(myDemo2);
    }

使用SpringObjenesis

这是Spring对Objenesis接口的一个实现。由Spring4.2之后提供的(ObjenesisCglibAopProxy可是Spring4.0就有了哦)

基本使用上,我们只需要换个实现就成:

代码语言:javascript
复制
Objenesis objenesis = new SpringObjenesis();

Spring为我们提供了一个isWorthTrying()方法:

代码语言:javascript
复制
	// 是否需要尝试:也就是说,它是否还没有被使用过,或者已知是否有效。方法返回true,表示值得尝试
	// 如果配置的Objenesis Instantiator策略被确定为不处理当前JVM。或者系统属性"spring.objenesis.ignore"值设置为true,表示不尝试了
	// 这个在ObjenesisCglibAopProxy创建代理实例的时候用到了。若不尝试使用Objenesis,那就还是用老的方式用空构造函数吧
	public boolean isWorthTrying() {
		return (this.worthTrying != Boolean.FALSE);
	}

Objenesis 和 class.newInstance的区别

从以上代码可以发现class构造器需要参数,而Objenesis可以绕过去, Objenesis主要应用场景:

  • 序列化,远程调用和持久化 -对象需要实例化并存储为到一个特殊的状态,而没有调用代码
  • 代理,AOP库和Mock对象 -类可以被子类继承而子类不用担心父类的构造器。
  • 容器框架 -对象可以以非标准的方式被动态实例化(比如Spring就是容器框架)。

Enhancer:CGLIB增强器

也是位于cglib相关的包内。org.springframework.cglib.proxy

CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架(例如Spring AOP)使用,为他们提供方法的interception(拦截)

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉

代码语言:javascript
复制
public class MainTest {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyDemo.class);
        // 注意此处得MethodInterceptor是cglib包下的   AOP联盟里还有一个MethodInterceptor
        enhancer.setCallback((MethodInterceptor) (o, method, args1, methodProxy) -> {
            System.out.println(method.getName() + "---方法拦截前");
            // 此处千万不能调用method得invoke方法,否则会死循环的 只能使用methodProxy.invokeSuper 进行调用
            //Object result = method.invoke(o, args1);
            Object result = methodProxy.invokeSuper(o, args1);
            System.out.println(method.getName() + "---方法拦截后");
            return result;
        });

        //MyDemo myDemo = (MyDemo) enhancer.create(); // 这里是要求必须有空的构造函数的
        MyDemo myDemo = (MyDemo) enhancer.create(new Class[]{String.class}, new Object[]{"fsx"});
        // 直接打印:默认会调用toString方法以及hashCode方法  此处都被拦截了
        System.out.println(myDemo);
        //System.out.println(myDemo.code);

    }
}

class MyDemo {
    public String code = "10";

    public MyDemo(String code) {
        this.code = code;
    }
}

输出:
toString---方法拦截前
hashCode---方法拦截前
hashCode---方法拦截后
toString---方法拦截后
com.fsx.maintest.MyDemo$$EnhancerByCGLIB$$b07b3819@7960847b
fsx

这样我们就简单的实现了,对一个对象进行增强。

还有一种创建代理实例的方式,就是我们只用Enhancer把Class类型创建出来,然后创建实例的工作交给Objenesis 这样我们就拜托了对构造函数的依赖

代码语言:javascript
复制
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyDemo.class);

        // 如国实用createClass方式来创建代理的实例  是不能直接添加callback得
        //enhancer.setCallback();
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new DefaultGeneratorStrategy());
        enhancer.setCallbackFilter(new CallbackHelper(MyDemo.class, null) {
            @Override
            protected Object getCallback(Method method) {
                return (MethodInterceptor) (o, method1, args1, methodProxy) -> {
                    System.out.println(method1.getName() + "---方法拦截前");
                    // 此处千万不能调用method得invoke方法,否则会死循环的 只能使用methodProxy.invokeSuper 进行调用
                    //Object result = method.invoke(o, args1);
                    Object result = methodProxy.invokeSuper(o, args1);
                    System.out.println(method1.getName() + "---方法拦截后");
                    return result;
                };
            }
        });
        enhancer.setCallbackTypes(new Class[]{MethodInterceptor.class});

        // 这里我们只生成Class字节码,并不去创建对象
        Class clazz = enhancer.createClass();
        // 创建对象的操作交给
        Objenesis objenesis = new SpringObjenesis();
        MyDemo myDemo = (MyDemo) objenesis.newInstance(clazz);

        System.out.println(myDemo);
        System.out.println(myDemo.code);

    }
输出:
com.fsx.maintest.MyDemo$$EnhancerBySpringCGLIB$$6558edaa@5700d6b1
null

这样即使你没有空的构造函数,我依然可议给你创建一个实例。


CGLIB整个过程如下

  • Cglib根据父类,Callback, Filter 及一些相关信息生成key
  • 然后根据key 生成对应的子类的二进制表现形式
  • 使用ClassLoader装载对应的二进制,生成Class对象,并缓存
  • 最后实例化Class对象,并缓存

生成二进制Class的方法

针对不同场景, CGlib准备了不同的Class生成方法

二进制文件存在在哪儿?

放在byte数组中,下面这行代码就截取于方法AbstractClassGenerator.create(Object key)

代码语言:javascript
复制
byte[] b = strategy.generate(this); 

然后通过 ReflectUtils.defineClass(className, b, loader)生成对应的Class实例,并缓存入cache2

Cglib如何把二进制Load生成的Class

上面说了,事ReflectUtils.defineClass这个方法:

代码语言:javascript
复制
    public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
        return defineClass(className, b, loader, PROTECTION_DOMAIN);
    }

    public static Class defineClass(String className, byte[] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception {
        Object[] args;
        Class c;
        if (DEFINE_CLASS != null) {
            args = new Object[]{className, b, new Integer(0), new Integer(b.length), protectionDomain};
            c = (Class)DEFINE_CLASS.invoke(loader, args);
        } else {
            if (DEFINE_CLASS_UNSAFE == null) {
                throw new CodeGenerationException(THROWABLE);
            }  

            args = new Object[]{className, b, new Integer(0), new Integer(b.length), loader, protectionDomain};
            c = (Class)DEFINE_CLASS_UNSAFE.invoke(UNSAFE, args);
        }

        Class.forName(className, true, loader);
        return c;
    }

注意

JDK代理只能针对实现了接口的类以反射的方式生成代理,而不能针对类 ,所以也叫接口代理。

CGLIB是针对类实现代理的,主要对指定的类以字节码转换的方式(ASM框架)生成一个子类,并重写其中的方法。

所以使用CGLIB做动态代理,必须要保证有一个空的构造函数。(那是之前,其实现在不需要了,因为我们有了Objenesis的帮助),但是类不能是Final的

  • 关于final方法
  • JDK代理:因为接口的方法不能使用final关键字,所以编译器就过不去
  • CGLIB代理:final修饰某个方法后,不报错。但也不会拦截了
  • 关于static方法
  • JDK代理:static修饰接口上的方法,要求有body体(JDK8后支持)。但是因为子类不能@Override了,所以编译就报错了
  • CGLIB代理:父类方法用static修饰后,子类也是无法进行重写的。因此不报错,但也不会拦截了 使用代理的时候,尽量不要使用final和static关键字
  • 关于非public方法
  • JDK代理:接口中的方法都是public的,所以对于它不存在这种现象
  • CGLIB代理:记住结论 只有private的方法不能被代理(因为子类无法访问),其余的访问权限级别的,都能够被正常代理。 简单的说就是只要子类能够访问的权限,都能够被正常代理
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义
  • 引子
  • 动态代理和静态代理回顾
  • AopProxy:Aop代理接口
    • JdkDynamicAopProxy—jdk生成动态代理对象
      • CglibAopProxy----cglib生成动态代理对象
        • ObjenesisCglibAopProxy—CglibAopProxy子类
          • 小结
          • Objenesis:另一种实例化对象的方式
            • 使用ObjenesisStd
              • 使用SpringObjenesis
                • Objenesis 和 class.newInstance的区别
                • Enhancer:CGLIB增强器
                  • CGLIB整个过程如下
                  • 注意
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档