Spring AOP原理之建立AopProxy代理对象

el/2024/3/2 12:27:11

在Spring AOP实现中,使用的核心技术是动态代理,而这种动态代理实际上是JDK的一个特性(在JDK 1.3以上的版本里,实现了动态代理模式)。通过JDK的动态代理特性,可以为任意Java对象创建代理对象,对于具体使用来说,这个特性是通过Java Reflection API来完成的。

看此篇文章之前,可以先看看 JDK动态代理机制,对动态代理有个基础的了解先。

设计原理

ProxyFactory的设计为中心,可以看到相关的类继承关系如图所示:

  • ProxyConfig里面封装了数据,为子类提供配置属性。
  • AdvisedSupport封装了AOP对通知Advice(Advice)和通知器(Advisor)的相关操作。这些操作对于不同的AOP的代理对象的生成都是一样的。但对于其体的AOP代理对象的创建,AdvisedSupport把它交始它的子类们去完成。
  • 对于ProxyCreatorSupport.可以将它看成是其子类创建AOP代理对象的一个辅助类。通过继承以上提到的‘类的功能实现。
  • 具体的AOP代理对象的生成,根据不同的需要,分别由ProxyFactoryBean, AspcctiProxyFactoryProxyFactory来完成。对于需要使用AspectJ的AOP应用,AspectJProxyFactory起到集成Spring和AspectJ的作用。对于使用Spring AOP的应用,ProxyFactoryBean和ProxyFactoy都提供了AOP功能的封装。

ProxyFactoryBean生成AopProxy代理对象

ProxyFactoryBean的^OP实现需要依翰JDK或者CGLIB提供的Proxy特性。从FactoryBean中获取对象.是以getObject()方法作为入口完成的。
先看AopProxy生成过程的时序图:

ProxyFactoryBean的入口getObject()开始:

  public Object getObject() throws BeansException {//初始化通知链this.initializeAdvisorChain();//这里对Singleton和prototype的类型进行区分,生成对应的proxyif (this.isSingleton()) {return this.getSingletonInstance(); //生成singleton的代理对象} else {if (this.targetName == null) {this.logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");}return this.newPrototypeInstance();  //生成prototype的代理对象}}//初始化通知链private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {if (!this.advisorChainInitialized) {if (!ObjectUtils.isEmpty(this.interceptorNames)) {if (this.beanFactory == null) {throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));}if (this.interceptorNames[this.interceptorNames.length - 1].endsWith("*") && this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {throw new AopConfigException("Target required after globals");}String[] var1 = this.interceptorNames;int var2 = var1.length;//添加advisors 链的调用,通过interceptorNames属性进行配置,interceptorNames通过IoC从配置bean中读取而来for(int var3 = 0; var3 < var2; ++var3) {String name = var1[var3];if (this.logger.isTraceEnabled()) {this.logger.trace("Configuring advisor or advice '" + name + "'");}if (name.endsWith("*")) {if (!(this.beanFactory instanceof ListableBeanFactory)) {throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");}this.addGlobalAdvisor((ListableBeanFactory)this.beanFactory, name.substring(0, name.length() - "*".length()));} else {Object advice;if (!this.singleton && !this.beanFactory.isSingleton(name)) {advice = new ProxyFactoryBean.PrototypePlaceholderAdvisor(name);} else {advice = this.beanFactory.getBean(name);}this.addAdvisorOnChainCreation(advice, name);}}}this.advisorChainInitialized = true;}//生成singleton的代理对象private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = this.freshTargetSource();if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) {//根据AOP框架来判断需要代理的接口Class<?> targetClass = this.getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}//设置代理对象的接口this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}super.setFrozen(this.freezeProxy);//使用ProxyFactory来生成需要的Proxy,  createAopProxy是其父亲中实现的方法this.singletonInstance = this.getProxy(this.createAopProxy());}return this.singletonInstance;}   //通过createAopProxy返回的AopProxy来得到代理对象protected Object getProxy(AopProxy aopProxy) {return aopProxy.getProxy(this.proxyClassLoader);}

看看ProxyCreatorSupport的创建AopProxy对象:

    protected final synchronized AopProxy createAopProxy() {if (!this.active) {this.activate();}//使用AopProxyFactory来取得AopProxy对象,AopProxyFactory是在构造函数中定义的,用的是DefaultAopProxyFactoryreturn this.getAopProxyFactory().createAopProxy(this);}   public ProxyCreatorSupport() {this.aopProxyFactory = new DefaultAopProxyFactory();}

接着是DefaultAopProxyFactory中的createAopProxy

 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {return new JdkDynamicAopProxy(config);} else {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.");} else {//如果targetClass是接口,使用JDK来生成,否者使用CGLIB来生成return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));}}}

通过上面的时序图和源码分析,可以看出ProxyFactoryBean生成AopProxy代理对象的基本过程。

前面介绍的ProxyFactoryBeanAopProxy代理对象和IoC容器配置之间起到了桥梁的作用。AopProxy代理对象可以由JDKCGLIB来生成。而JdkDynamicAopProxyCglibAopProxy实现的都是通过AopProxy接口。他们的继承关系如下:

JDK生成AopProxy代理对象

源码如下:

 public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}//从advised对象中取得代理对象的代理接口配置Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);//调用JDK生成代理对象return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

在生成代理对象时,需要指明三个参数,一个是类装载器,一个是代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口。

CGLIB生成AopProxy代理对象

源码如下:


public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());}//从advised中取得在IoC容器中配里的target对象try {Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;int x;if (ClassUtils.isCglibProxyClass(rootClass)) {proxySuperClass = rootClass.getSuperclass();Class<?>[] additionalInterfaces = rootClass.getInterfaces();Class[] var5 = additionalInterfaces;int var6 = additionalInterfaces.length;for(x = 0; x < var6; ++x) {Class<?> additionalInterface = var5[x];this.advised.addInterface(additionalInterface);}}this.validateClassIfNecessary(proxySuperClass, classLoader);//验证代理对象的接口设置//创建并配置CGLIB的Enhancer.这个Enhancer对象是CGLIB的主要操作类Enhancer enhancer = this.createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}//设置Enhancer对象,包括设置代理接口,回调方法//来自advised的IoC配置,比如使用AOP的DynamicAdvisedlnterceptor拦截器enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));Callback[] callbacks = this.getCallbacks(rootClass);Class<?>[] types = new Class[callbacks.length];for(x = 0; x < types.length; ++x) {types[x] = callbacks[x].getClass();}enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);//通过Enhancer生成代理对象return this.createProxyClassAndInstance(enhancer, callbacks);} catch (IllegalArgumentException | CodeGenerationException var9) {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", var9);} catch (Throwable var10) {throw new AopConfigException("Unexpected AOP exception", var10);}}

http://www.ngui.cc/el/4466048.html

相关文章

Spring AOP原理之拦截器调用的实现

接上文 Spring AOP原理之建立AopProxy代理对象 在Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候&#xff0c;相关的拦截器已经配置到代理对象中去了&#xff0c;拦截器在代理对象中起作用是通过对这些方法的回调来完成的。如果使用JDK的Proxy来生成代理对象&…

Spring MVC原理之Spring应用上下文(IoC容器)在Web容器中的启动分析

Spring IoC是一个独立的模块&#xff0c;它并不是直接在Web容器中发挥作用的。如果要在Web环境中使用IoC容器&#xff0c;需要Spring为IoC设计一个启动过程&#xff0c;把IoC容器导人&#xff0c;并在Web容器中建立起来。具体说来&#xff0c;这个启动过程是和Web容器的启动过程…

Spring MVC原理之Spring MVC的设计与实现

接上文 SpringMVC原理之Spring应用上下文&#xff08;Ioc容器&#xff09;在Web容器中的启动分析。 在前文的分析过程中&#xff0c;了解了 Spring的上下文体系通过ContextLoader和DispatcherServiet建立并初始化的过程。在完成对ContextLoaderListener的初始化以后&#xff0c…

Spring JDBC的设计与实现

设计原理 在Spring JDBC中&#xff0c;JdbcTemplate 是一个主要的模板类&#xff0c;它的类继承关系如图&#xff1a; 从类继承关系上来看&#xff0c;JdbcTemplate继承了基类JdbcAccessor和接口类JdbcOperation。在基类JdbcAccessor的设计中&#xff0c;对DataSource数据源…

Spring事务处理浅析

类层次结构 在Spring的事务处理模块中.可以看到的类层次结构如图&#xff1a; 可以看到&#xff0c;Spring事务处理模块是通过AOP功能来实现声明式事务处理的&#xff0c;比如事务属性的配置和读取&#xff0c;事务对象的抽象等。因此&#xff0c;在Spring事务处理中&#xff…

dubbo管理控制台dubbo-admin安装

资源&#xff1a; dubbo源码 和 中文文档 下载源码 下载dubbo-admin模块代码&#xff0c;这个还真不太好找&#xff0c;可能是因为dubbo迁移至Apache 维护后&#xff0c;代码还没迁移好&#xff1f;&#xff1f;&#xff1f; 我是在 https://github.com/apache/incubator-du…

React Native 项目环境配置、调试以及打包

去年在做React Native混合开发的时候&#xff0c;写过几篇笔记&#xff1a; react-native对android物理返回键back的监听以及基类封装 react native导航navigator react-native 与安卓端通信 android 端集成react native Fetch 网络请求简单封装&#xff0c;支持超时入口 …

Rest 概要

REST RESTful Representational State Transfer。是在因特网上提供计算机系统之间的互操作性的一种方式。基于Http协议的资源传递&#xff0c;包括JSON、XML和文本等。 统一接口 资源识别&#xff08;Identification of resources&#xff09; URI&#xff08;Uniform Resou…

构建一个REST风格的Web服务

你需要什么 大约15分钟IntelliJ IDEA或其他编辑器JDK 1.8或更高版本Maven 3.2 你会建立什么 您将在以下地址构建一个将接受HTTP GET请求的服务&#xff1a; http://localhost:8080/greeting 会返回一个JSON 格式的数据&#xff1a; {"id":1,"content"…

调度任务Scheduling Tasks

你需要什么 大约15分钟IntelliJ IDEA或其他编辑器JDK 1.8或更高版本Maven 3.2 你会建立什么 您将构建一个应用程序&#xff0c;该应用程序使用Spring的 Scheduled 注解&#xff0c;每5秒打印一次当前时间。 构建步骤 1、添加maven依赖 <dependency><groupId>…