Spring5参考指南
  • 简介
  • 前言
    • 1. “Spring”代表什么
    • 2. Spring和Spring框架的历史
    • 3. 设计哲学
    • 4. 反馈和贡献
    • 5. 开始
  • 核心技术
    • 1. IoC容器
      • 1.1 IoC容器和Beans介绍
      • 1.2 IoC容器概述
      • 1.3 Bean概述
      • 1.4 依赖
      • 1.5 Bean作用域
      • 1.6 自定义Bean
      • 1.7 Bean的继承
      • 1.8 容器扩展点
      • 1.9 基于注解的容器配置
      • 1.10 类路径扫描和托管组件
      • 1.11 使用JSR 330标准注解
      • 1.12 基于Java的容器配置
      • 1.13 环境抽象
      • 1.14 注册LoadTimeWeaver
      • 1.15 ApplicationContext的其他功能
      • 1.16 BeanFactory
    • 2.资源
      • 2.1介绍
      • 2.2资源接口
      • 2.3内置资源实现
      • 2.4ResourceLoader
      • 2.5ResourceLoaderAware接口
      • 2.6资源作为依赖
      • 2.7应用程序上下文和资源路径
    • 3.验证,数据绑定,和类型转换
      • 3.1使用Spring Validator接口
      • 3.2将代码解析为错误消息
      • 3.3bean操作和BeanWrapper
      • 3.4Spring类型转换
      • 3.5Spring字段格式化
      • 3.6配置全局Date和Time格式
      • 3.7Spring验证
    • 4.SpEL Spring表达式语言
      • 4.1求值
      • 4.2bean定义中的表达式
      • 4.3语言引用
    • 5.Spring AOP
      • 5.1什么是AOP
      • 5.1Spring AOP的能力和目标
      • 5.3AOP代理
      • 5.4@AspectJ 支持
      • 5.5基于Schema的AOP支持
      • 5.6选择要使用的AOP声明样式
      • 5.7混合Aspect类型
      • 5.8代理机制
      • 5.9程序创建@AspectJ代理
      • 5.10在Spring应用程序中使用AspectJ
      • 5.11更多资源
    • 6.Spring AOP APIs
      • 6.1Pointcut API
      • 6.2Advice API
      • 6.3Advisor API
      • 6.4使用ProxyFactoryBean来创建AOP代理
      • 6.5简介的代理定义
      • 6.6使用ProxyFactory创建AOP代理
      • 6.7操作被通知的对象
      • 6.8使用auto-proxy功能
      • 6.9使用TargetSource的实现
      • 6.10定义新的Advice Types
    • 7.Null-safety
    • 8.数据缓存和解码器
    • 9.附录
      • 9.1XML Schemas
      • 9.2创建XML Schemas
  • 测试
    • 1.Spring测试介绍
    • 2.单元测试
      • 2.1Mock Objects
      • 2.2单元测试支持类
    • 3.集成测试
      • 3.1概览
      • 3.2集成测试的目的
      • 3.3JDBC测试支持
      • 3.4注解
      • 3.5Spring TestContext框架
      • 3.6Spring MVC测试框架
      • 3.7WebTestClient
    • 4.更多资源
  • 数据访问
    • 1.事务管理
    • 2.DAO支持
    • 3.JDBC
      • 3.1选择JDBC数据库访问方法
      • 3.2包层次结构
      • 3.3使用JDBC核心类控制基本JDBC处理和错误处理
      • 3.4控制数据库连接
      • 3.5JDBC批处理操作
      • 3.6使用SimpleJdbc
      • 3.7将JDBC操作建模为Java对象
      • 3.8参数和数据值处理的常见问题
      • 3.9嵌入式数据库支持
      • 3.10初始化数据源
    • 4.ORM
      • 4.1Spring ORM介绍
      • 4.2ORM集成的一般注意事项
      • 4.3Hibernate
      • 4.4JPA
    • 5.使用Object-XML映射封装XML
  • Web Servlet
    • 1. Spring Web MVC
      • 1.1 DispatcherServlet
      • 1.2 Filters
      • 1.3 Controllers注解
      • 1.4 URI链接
      • 1.5 异步请求
      • 1.6 CORS
      • 1.7 Web Security
      • 1.8 HTTP Caching
      • 1.9 View技术
      • 1.10 MVC配置
      • 1.11 HTTP/2
    • 2. REST客户端
    • 3. 测试
    • 4. WebSockets
      • 4.1 WebSocket介绍
      • 4.2 WebSocket API
      • 4.3 SockJS Fallback
      • 4.4 STOMP
  • Web Reactive
    • 1.Spring WebFlux
      • 1.1 Overview
      • 1.2 Reactive Core
      • 1.3 DispatcherHandler
      • 1.4 Annotated Controllers
      • 1.5 Functional Endpoints
      • 1.6 URI Links
      • 1.7 CORS
      • 1.8 Web Security
      • 1.9 View Technologies
      • 1.10 HTTP Caching
      • 1.11 WebFlux Config
      • 1.12 HTTP/2
    • 2.WebClient
    • 3.WebSockets
    • 4.测试
    • 5.Reactive库
由 GitBook 提供支持
在本页
  • 6.9 使用TargetSource的实现
  • 6.9.1 热交换目标源
  • 6.9.2 Pooling Target Sources
  • 6.9.3 Prototype Target Sources
  • 6.9.4 ThreadLocal Target Sources

这有帮助吗?

  1. 核心技术
  2. 6.Spring AOP APIs

6.9使用TargetSource的实现

6.9 使用TargetSource的实现

Spring提供了TargetSource的概念,用org.springframework.aop.TargetSource接口表示。此接口负责返回实现连接点的“目标对象”。每次AOP代理处理方法调用时,都会要求TargetSource实现一个目标实例。

使用SpringAOP的开发人员通常不需要直接使用TargetSource实现,但这提供了支持池、热交换和其他复杂目标的强大方法。例如,池目标源可以通过使用池来管理实例,为每次调用返回不同的目标实例。

如果不指定TargetSource,则使用默认实现包装本地对象。每次调用都会返回相同的目标(如你所期望的那样)。

本节的其余部分描述了Spring提供的标准目标源以及如何使用它们。

当使用自定义目标源时,你的目标通常需要是原型而不是单例bean定义。这允许Spring在需要时创建新的目标实例。

6.9.1 热交换目标源

存在org.springframework.aop.target.HotSwappableTargetSource以允许AOP代理的目标切换,同时允许调用方保留对它的引用。

更改目标源的目标将立即生效。HotSwappableTargetSource是线程安全的。

你可以使用HotSwappableTargetSource上的swap()方法更改目标,如下示例所示:

HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
Object oldTarget = swapper.swap(newTarget);

下面是需要的XML定义:

<bean id="initialTarget" class="mycompany.OldTarget"/>

<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
    <constructor-arg ref="initialTarget"/>
</bean>

<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="swapper"/>
</bean>

swap()的执行改变了swappable bean的目标。持有对该bean的引用的客户端不知道该更改,并且立即开始使用新的目标。

尽管此示例不添加任何advice(不需要添加advice以使用TargetSource),但任何TargetSource都可以与任意advice结合使用。

6.9.2 Pooling Target Sources

使用pooling target source为无状态会话EJB提供了类似的编程模型,其中维护了相同实例的池,方法调用将释放池中的对象。

Spring池和SLSB池的一个重要区别是Spring池可以应用于任何POJO。与一般的Spring一样,此服务可以以非侵入性的方式应用。

Spring支持Commons Pool 2.2,它提供了一个相当有效的池实现。你需要应用程序类路径上的commons-pool来使用此功能。你还可以将org.springframework.aop.target.AbstractPoolingTargetSource子类化,以支持任何其他池API。

在Spring Framework 4.2中,Commons Pool 1.5+已不被推荐使用。

下面是一个配置的例子:

<bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject"
        scope="prototype">
    ... properties omitted
</bean>

<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
    <property name="targetBeanName" value="businessObjectTarget"/>
    <property name="maxSize" value="25"/>
</bean>

<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="poolTargetSource"/>
    <property name="interceptorNames" value="myInterceptor"/>
</bean>

请注意,目标对象(前面示例中的BusinessObjectTarget)必须是原型。这允许poolingTargetSource实现创建目标的新实例,以便在必要时扩大池。有关其属性的信息,请参阅AbstractPoolingTargetSource的JavaDoc和你希望使用的具体子类。maxSize是最基本的属性,并必须要被设置。

在这种情况下,myInterceptor是需要在相同的IOC上下文中定义的拦截器的名称。但是,不需要指定拦截器来使用池。如果只需要池而不需要其他建议,那么根本不要设置interceptorNames属性。

你可以将Spring配置为能够将任何池对象强制转换为org.springframework.aop.target.PoolingConfig接口,该接口通过简介公开池的配置和当前大小的信息。你需要定义类似以下内容的顾问:

<bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="poolTargetSource"/>
    <property name="targetMethod" value="getPoolingConfigMixin"/>
</bean>

通过对AbstractPoolingTargetSource类调用一个方便的方法来获得此Advisor,因此使用了MethodInvokingFactoryBean。此顾问的名称(此处为PoolConfigdVisor)必须位于公开池对象的ProxyFactoryBean中拦截器名称的列表中。

其定义如下:

PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
System.out.println("Max pool size is " + conf.getMaxSize());

通常不需要Pooling无状态服务对象。我们不认为这应该是默认的选择,因为大多数无状态对象都是自然线程安全的,如果缓存资源,实例池也会有问题。

使用自动代理可以使池的使用更加简单。TargetSource的实现可以被用在任何auto-proxy的创建者。

6.9.3 Prototype Target Sources

设置“prototype”目标源类似于设置池TargetSource。在这种情况下,每次方法调用都会创建目标的新实例。虽然在现代的JVM中创建新对象的成本并不高,但是连接新对象(满足其IOC依赖性)的成本可能更高。因此,如果没有很好的理由,你不应该使用这种方法。

为此,你可以修改前面显示的poolTargetSource定义,如下所示(为了清晰起见,我们还更改了名称):

<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource">
    <property name="targetBeanName" ref="businessObjectTarget"/>
</bean>

唯一的属性是目标bean的名称。在TargetSource实现中使用继承以确保一致的命名。与池目标源一样,目标bean必须是原型bean定义。

6.9.4 ThreadLocal Target Sources

如果需要为每个传入请求(即每个线程)创建一个对象,则ThreadLocal目标源非常有用。ThreadLocal的概念提供了一个JDK范围的工具,可以透明地将资源存储在线程旁边。设置ThreadLocalTargetSource与其他类型的目标源的说明几乎相同,如下示例所示:

<bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource">
    <property name="targetBeanName" value="businessObjectTarget"/>
</bean>

ThreadLocal实例在多线程和多类加载器环境中错误地使用它们时会出现严重问题(可能导致内存泄漏)。你应该始终考虑在其他类中包装一个threadlocal,而不要直接使用threadlocal本身(包装类中除外)。此外,你应该始终记住正确地设置和取消设置(后者只涉及对ThreadLocal.set(null))线程的本地资源。在任何情况下都应进行取消设置,因为不取消设置可能会导致问题行为。Spring的threadLocal支持为你提供了这一点,应该始终考虑在没有其他适当处理代码的情况下使用threadLocal实例。

上一页6.8使用auto-proxy功能下一页6.10定义新的Advice Types

最后更新于3年前

这有帮助吗?