前言
会更新AOP 系列源码文章 主要更新目录
篇幅问题 会分章程更新
创建代理
AbstractAutoProxyCreator.createProxy():根据增强方法创建代理对象
-
ProxyFactory proxyFactory = new ProxyFactory():无参构造 ProxyFactory,此处讲解一下两种有参构造方法:-
public ProxyFactory(Object target):
public ProxyFactory(Object target) { // 将目标对象封装成 SingletonTargetSource 保存到父类的字段中 setTarget(target); // 获取目标对象 class 所有接口保存到 AdvisedSupport 中的 interfaces 集合中 setInterfaces(ClassUtils.getAllInterfaces(target)); }ClassUtils.getAllInterfaces(target) 底层调用 getAllInterfacesForClassAsSet(java.lang.Class<?>, java.lang.ClassLoader):
-
if (clazz.isInterface() && isVisible(clazz, classLoader)):- 条件一:判断当前目标对象是接口
- 条件二:检查给定的类在给定的 ClassLoader 中是否可见
-
Class<?>[] ifcs = current.getInterfaces():拿到自己实现的接口,拿不到接口实现的接口 -
current = current.getSuperclass():递归寻找父类的接口,去获取父类实现的接口
-
-
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor):
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) { // 添加一个代理的接口 addInterface(proxyInterface); // 添加通知,底层调用 addAdvisor addAdvice(interceptor); }addAdvisor(pos, new DefaultPointcutAdvisor(advice)):Spring 中 Advice 对应的接口就是 Advisor,Spring 使用 Advisor 包装 Advice 实例
-
-
proxyFactory.copyFrom(this):填充一些信息到 proxyFactory -
if (!proxyFactory.isProxyTargetClass()):条件成立说明 proxyTargetClass 为 false(默认),两种配置方法:<aop:aspectj-autoproxy proxy-target-class="true"/>:强制使用 CGLIB@EnableAspectJAutoProxy(proxyTargetClass = true)
if (shouldProxyTargetClass(beanClass, beanName)):如果 bd 内有 preserveTargetClass = true ,那么这个 bd 对应的 class 创建代理时必须使用 CGLIB,条件成立设置 proxyTargetClass 为 trueevaluateProxyInterfaces(beanClass, proxyFactory):根据目标类判定是否可以使用 JDK 动态代理-
targetInterfaces = ClassUtils.getAllInterfacesForClass():获取当前目标对象 class 和父类的全部实现接口 -
boolean hasReasonableProxyInterface = false:实现的接口中是否有一个合理的接口 -
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0):遍历所有的接口,如果有任意一个接口满足条件,设置 hRPI 变量为 true- 条件一:判断当前接口是否是 Spring 生命周期内会回调的接口
- 条件二:接口不能是 GroovyObject、Factory、MockAccess 类型的
- 条件三:找到一个可以使用的被代理的接口
-
if (hasReasonableProxyInterface):有合理的接口,将这些接口设置到 proxyFactory 内 -
proxyFactory.setProxyTargetClass(true):没有合理的代理接口,强制使用 CGLIB 创建对象
-
advisors = buildAdvisors(beanName, specificInterceptors):匹配目标对象 clazz 的 Advisors,填充至 ProxyFactory -
proxyFactory.setPreFiltered(true):设置为 true 表示传递给 proxyFactory 的 Advisors 信息做过基础类和方法的匹配 -
return proxyFactory.getProxy(getProxyClassLoader()):创建代理对象public Object getProxy() { return createAopProxy().getProxy(); }DefaultAopProxyFactory.createAopProxy(AdvisedSupport config):参数是一个配置对象,保存着创建代理需要的生产资料,会加锁创建,保证线程安全
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 条件二为 true 代表强制使用 CGLIB 动态代理 if (config.isOptimize() || config.isProxyTargetClass() || // 条件三:被代理对象没有实现任何接口或者只实现了 SpringProxy 接口,只能使用 CGLIB 动态代理 hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException(""); } // 条件成立说明 target 【是接口或者是已经被代理过的类型】,只能使用 JDK 动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); // 使用 JDK 动态代理 } return new ObjenesisCglibAopProxy(config); // 使用 CGLIB 动态代理 } else { return new JdkDynamicAopProxy(config); // 【有接口的情况下只能使用 JDK 动态代理】 } }JdkDynamicAopProxy.getProxy(java.lang.ClassLoader):获取 JDK 的代理对象
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { // 配置类封装到 JdkDynamicAopProxy.advised 属性中 this.advised = config; } public Object getProxy(@Nullable ClassLoader classLoader) { // 获取需要代理的接口数组 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); // 查找当前所有的需要代理的接口,看是否有 equals 方法和 hashcode 方法,如果有就做一个标记 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 该方法最终返回一个代理类对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); // classLoader:类加载器 proxiedInterfaces:生成的代理类,需要实现的接口集合 // this JdkDynamicAopProxy 实现了 InvocationHandler }AopProxyUtils.completeProxiedInterfaces(this.advised, true):获取代理的接口数组,并添加 SpringProxy 接口
-
specifiedInterfaces = advised.getProxiedInterfaces():从 ProxyFactory 中拿到所有的 target 提取出来的接口if (specifiedInterfaces.length == 0):如果没有实现接口,检查当前 target 是不是接口或者已经是代理类,封装到 ProxyFactory 的 interfaces 集合中
-
addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class):判断目标对象所有接口中是否有 SpringProxy 接口,没有的话需要添加,这个接口标识这个代理类型是 Spring 管理的addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class):判断目标对象的所有接口,是否已经有 Advised 接口addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)):判断目标对象的所有接口,是否已经有 DecoratingProxy 接口int nonUserIfcCount = 0:非用户自定义的接口数量,接下来要添加上面的三个接口了proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount]:创建一个新的 class 数组,长度是原目标对象提取出来的接口数量和 Spring 追加的数量,然后进行 System.arraycopy 拷贝到新数组中int index = specifiedInterfaces.length:获取原目标对象提取出来的接口数量,当作 indexif(addSpringProxy):根据上面三个布尔值把接口添加到新数组中return proxiedInterfaces:返回追加后的接口集合
JdkDynamicAopProxy.findDefinedEqualsAndHashCodeMethods():查找在任何定义在接口中的 equals 和 hashCode 方法
-
for (Class<?> proxiedInterface : proxiedInterfaces):遍历所有的接口-
Method[] methods = proxiedInterface.getDeclaredMethods():获取接口中的所有方法 -
for (Method method : methods):遍历所有的方法if (AopUtils.isEqualsMethod(method)):当前方法是 equals 方法,把 equalsDefined 置为 trueif (AopUtils.isHashCodeMethod(method)):当前方法是 hashCode 方法,把 hashCodeDefined 置为 true
-
if (this.equalsDefined && this.hashCodeDefined):如果有一个接口中有这两种方法,直接返回
-
-
本文正在参加「金石计划 . 瓜分6万现金大奖」