什么是网站地址,杭州工程建设网,百度一下知道官网,wordpress主题生成工具前言
在Spring框架中#xff0c;TargetSource是一个接口#xff0c;用于封装获取目标对象#xff08;也就是被代理的对象#xff09;的逻辑。它的主要作用是提供代理对象使用的目标对象#xff0c;并且允许在运行时动态地切换目标对象。TargetSource在Spring的AOP#x…前言
在Spring框架中TargetSource是一个接口用于封装获取目标对象也就是被代理的对象的逻辑。它的主要作用是提供代理对象使用的目标对象并且允许在运行时动态地切换目标对象。TargetSource在Spring的AOP面向切面编程中非常重要它定义了代理对象的目标是谁以及在何时获取目标对象。
具体来说TargetSource接口定义了以下两个方法 getTarget()这个方法用于获取目标对象。AOP代理对象在执行方法时会先调用getTarget()方法获取目标对象然后再在目标对象上执行相应的方法。 releaseTarget(Object target)这个方法用于释放目标对象。在一些特殊的场景中可能需要手动释放目标对象以便它可以被垃圾回收或者被缓存起来以供下次使用。 isStatic() 方法该方法用于指示目标对象是否是静态的。如果目标对象是静态的那么TargetSource可以在代理创建时确定代理对象的类型从而进行更好的性能优化。如果目标对象是动态的例如在运行时根据条件切换不同的实例则返回false。 getTargetClass() 方法 该方法返回代理的目标对象的类类型。在使用基于接口的代理例如JDK动态代理时这个方法返回接口的类型。在使用基于类的代理例如CGLIB代理时这个方法返回目标对象的类型。这个信息通常用于确定代理的类型。
TargetSource的作用体现在以下几个方面 AOP代理 在AOP中TargetSource允许你控制代理对象的目标对象是谁。例如你可以创建一个TargetSource实现根据特定条件选择不同的目标对象。这种灵活性使得你能够动态地选择在代理对象上应用哪些切面逻辑。 性能优化 通过TargetSource你可以实现一些性能优化的技术比如对象池Object Pooling。你可以将对象缓存起来而不是每次都创建新的对象从而减少了对象的创建和销毁开销。 多数据源切换 在一些应用中可能需要根据不同的请求选择不同的数据源。通过自定义的TargetSource你可以根据请求动态切换目标数据库。 状态管理和缓存 TargetSource可以用于状态管理和缓存策略。你可以在getTarget()方法中加入状态管理逻辑确保每次获取到的目标对象都是处于特定状态的。同时也可以在这里实现缓存逻辑将经常使用的对象缓存起来提高系统性能。
官方TargetSource地址
Spring中TargetSource的默认实现
PrototypeTargetSource、SingletonTargetSource、SimpleBeanTargetSource、ThreadLocalTargetSource 和 CommonsPool2TargetSource 都是 Spring 框架中的 TargetSource 实现它们分别适用于不同的场景具有不同的特点和用途。
1. PrototypeTargetSource:
作用 PrototypeTargetSource 用于原型prototype的 Bean每次请求时都会创建一个新的实例。特点 适用于需要在每次请求时都创建新实例的目标对象保持状态隔离。
2. SingletonTargetSource:
作用 SingletonTargetSource 用于单例的 Bean整个应用程序生命周期内只有一个实例。特点 适用于状态无关的、可共享的目标对象。
3. SimpleBeanTargetSource:
作用 SimpleBeanTargetSource 用于简单的 Bean 对象通常是指那些没有接口或者特殊要求的类。特点 将普通的 Java 对象转化为 Spring AOP 可以处理的代理对象。
4. ThreadLocalTargetSource:
作用 ThreadLocalTargetSource 将目标对象保存在 ThreadLocal 中使得每个线程都有自己的目标对象实例。特点 适用于多线程环境下每个线程都拥有独立的目标对象实例。
5. CommonsPool2TargetSource:
作用 CommonsPool2TargetSource 使用 Apache Commons Pool 2 来管理目标对象的池化。特点 可以灵活地控制对象池的大小和行为适用于需要对象池管理的场景。
区别和使用场景总结 PrototypeTargetSource 和 SingletonTargetSource 分别适用于需要每次请求都创建新实例和整个应用程序生命周期内共享同一个实例的场景。 SimpleBeanTargetSource 适用于没有接口和特殊要求的普通 Java 对象。 ThreadLocalTargetSource 适用于多线程环境需要每个线程都有独立目标对象实例的场景。 CommonsPool2TargetSource 适用于需要对象池管理的场景可以灵活地控制对象池的行为比如最大池大小、最小池大小等。
普通的 AOP 代理创建使用的 TargetSource
日常工作中使用Spring AOP 代理 bean 基本都会走 AutoProxyCreator#wrapIfNecessary() 来进行创建。 它使用的 TargetSource 是 SingletonTargetSource也就是每次 SingletonTargetSource#getTarget() 都返回的是同一个对象。 TargetSource#isStatic()
在Spring AOP中TargetSource可以分为“静态”和“动态”两类这两者的区别在于代理对象的目标对象是在代理创建时就确定好静态还是在运行时动态确定动态。
1. 静态TargetSource:
目标对象确定性 静态TargetSource在代理对象创建时目标对象就已经确定了它不会随着时间或者特定条件的改变而改变。通常静态TargetSource的目标对象是单例Singleton的即整个应用程序生命周期内只有一个实例。作用 静态TargetSource适用于那些在整个应用程序中共享同一个实例的目标对象这种目标对象通常是无状态的、可共享的例如服务类、工具类等。使用静态TargetSource可以带来性能上的优势因为代理对象只需要在创建时确定一次目标对象即可。
2. 动态TargetSource:
目标对象的动态性 动态TargetSource在代理对象创建后可以在运行时动态地改变代理对象的目标对象。这种改变可以基于特定的条件、用户权限、请求内容等动态决定。动态TargetSource的目标对象可以随着时间、请求、或者其他因素的改变而改变。作用 动态TargetSource适用于那些需要根据特定条件或者动态情况来确定目标对象的场景。例如在多数据源切换时根据用户的请求或者业务逻辑需要选择不同的数据库连接。动态TargetSource允许在运行时动态选择代理的目标对象。
作用比较 静态TargetSource适用于那些整个应用程序生命周期内只需要一个实例的目标对象比如无状态的服务类。 动态TargetSource适用于那些需要根据条件动态选择目标对象的场景比如根据用户权限、请求内容等动态选择不同的实例。
选择静态还是动态的TargetSource取决于你的应用需求。如果你的目标对象是无状态的、可共享的使用静态TargetSource可以带来性能上的优势。如果你的目标对象是有状态的、需要根据条件动态切换的使用动态TargetSource可以实现更灵活的代理目标对象选择逻辑。
在Spring AOP中CglibAopProxy和JdkDynamicAopProxy是两种不同的AOP代理方式分别使用CGLIBCode Generation Library和JDK动态代理技术来创建代理对象。这两者在处理isStatic()方法时有所不同。
3. CglibAopProxy:
在CglibAopProxy中StaticUnadvisedExposedInterceptor 和 DynamicUnadvisedExposedInterceptor 是两个不同的拦截器类。它们分别用于处理静态代理和动态代理。
StaticUnadvisedExposedInterceptor:
StaticUnadvisedExposedInterceptor 主要用于处理基于接口的静态代理它的实例被用于拦截那些实现了接口的目标对象。这个拦截器的构造函数接受一个目标对象作为参数并且这个目标对象是在拦截器创建时就已经确定的是静态的不会在运行时改变。
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget())在这里this.advised.getTargetSource().getTarget() 是一个静态的目标对象它在代理创建时就已经确定不会在后续的运行时动态改变。
DynamicUnadvisedExposedInterceptor:
DynamicUnadvisedExposedInterceptor 用于处理CGLIB或者其他动态代理方式创建的代理对象。这个拦截器的构造函数接受一个TargetSource作为参数TargetSource可以动态地确定目标对象。DynamicUnadvisedExposedInterceptor 的目标对象是动态的它可能会在运行时根据条件或者其他因素改变。
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource())在这里this.advised.getTargetSource() 返回的是一个TargetSource对象这个TargetSource可能会根据特定的条件在运行时切换目标对象。因此DynamicUnadvisedExposedInterceptor 用于处理动态代理目标对象可能在运行时发生改变。 4. JdkDynamicAopProxy:
Jdk的isStatic的处理和cglib有点区别Jdk Proxy每次调用会通过TargetSource#getTarget()获取目标对象。最后通过如果isStatic为false得时候会去releaseTarget。