Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from insaneXs/master
翻译完11章剩余部分
- Loading branch information
Showing
3 changed files
with
98 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
Spring通过`org.springframework.aop.TargetSource`接口提供了TargetSource的概念。这个接口负责返回实现了Joint point的目标对象。`TargetSource`在每次AOP代理处理方法调用时,都会被要求产生一个目标对象。 | ||
使用Spring AOP的开发者通常不需要直接使用TargetSources,但这为池,热交换和其他复杂的目标提供了强大的支持。比如,一个池化的TargetSource可以为每个调用返回不同的目标对象,并用池管理这些实例。 | ||
如果你没有特指TargetSource,会使用包装本地对象的默认实现。(正如你所期望的)每次调用返回的都是相同的目标。让我们看一下Spring提供的标准的target Source和你该如何使用它们。 | ||
>当使用自定义的target source时,你的目标通常要是原型的,而非单例的。这允许Spring在需要时创建新的实例。 | ||
### 12.10.1 Hot swappable target sources | ||
`org.springframework.aop.target.HotSwappleTargetSource`的存在允许AOP 代理的目标在调用者仍持有它们引用的情况下替换掉它们。 | ||
改变target source的目标会被立刻生效。`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的目标。持有这个引用的客户端并不会知道这个变化的过程,但是变化立即生效了。 | ||
尽管这个例子中没有添加任何的通知——并且在使用`TargetSource`时不需要添加通知——当然任何`TargetSource`可以和任意通知结合使用。 | ||
#### 12.10.2 Pooling target sources | ||
池化的target source提供了和无状态会话EJB相似的编程模型,池中维护着不同的实例,当方法被调用时,可以从池中获取对象。 | ||
Spring池和SLSB池关键的区别是Spring池可以应用于任何POJO。通常对Spring而言,服务可以以非入侵的方式被应用。 | ||
Spring提供了对Commons Pool 2.2开箱即用的支持,它提供了相当有效率池化实现。如果要使用这个特性,你需要将commons-pool的Jar包添加到应用程序的类路径下。也可以继承`org.springframework.aop.target.AbstractPoolingTargetSource`来支持其他的池化API。 | ||
> Spring框架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`的实现在需要的时候让池创建一个新的实例。查看Java文档了解`AbstractPoolingTargetSource`和你所希望使用的具体子类的属性:最基础的属性时"maxSize",且必须要保证存在这个属性。 | ||
在这个例子中,"myInterceptor"是定义在同一个IoC容器中的拦截器。然而,在使用池时不需要指定拦截器。如果你只希望池化且没有其他的通知,那就不需要设置interceptorsNames的属性。 | ||
可以通过Spring配置让被池管理的对象能够转成`org.springframework.aop.target.PoolingConfig`接口,它可以通过引入将池的当前大小和配置信息传递出来。你需要添加一个像这样的advisor: | ||
|
||
``` | ||
<bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | ||
<property name="targetObject" ref="poolTargetSource"/> | ||
<property name="targetMethod" value="getPoolingConfigMixin"/> | ||
</bean> | ||
``` | ||
因为我们使用了MethodInvokingFactoryBean,advisor会在`AbstractPoolingTargetSource`类调用方法时被获得。这个advisor的名字(这里时"poolingConfigAdvisor")一定要在ProxyFactoryBean的拦截器名字的列表中,以暴露被池化的对象。 | ||
可以像下面这样转型: | ||
|
||
``` | ||
PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); | ||
System.out.println("Max pool size is " + conf.getMaxSize()); | ||
``` | ||
> 通查,池化管理无状态的服务对象是不必要的。我们不认为这要作为默认的选择,因为大多数无状态的对象时线程安全的,并且如果资源被缓存的话是有问题的。 | ||
更简单的池可以使用自动代理。可以为自动代理创造器设置TargetSources。 | ||
### 12.10.3 Prototype target sources | ||
设置“原型”的target source和池化TargetSource很像。这种情况下,秒内次调用方法时,都会为目标创建新的实例。尽管在现代的JVM中,创建新对象的话费并不是很高,但(满足IoC依赖的)织入的代价可能会很高。因此在没有特别好的理由下,你不应该使用这个方法。 | ||
为了实现这点,你需要将上面的`poolTargetSource`定义做些修改(为了更清晰,我还改了名字。) | ||
|
||
``` | ||
<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource"> | ||
<property name="targetBeanName" ref="businessObjectTarget"/> | ||
</bean> | ||
``` | ||
这里只有一个属性:目标bean的名字。它继承而来,保证了在TargetSource的各实现中命名的一致性。和pooling target source一样,(prototype target source的)目标bean必须要是原型的bean定义。 | ||
### 12.10.4 ThreadLocal taget sources | ||
`ThreadLocal` target sources在你需要为每个请求(即每个线程)创建一个对象时十分有用。`ThreadLocal`的概念是在JDK级别为每个线程透明的存储资源。设置`TheadLocalTargetSource`和其他说明过的target source类型很相似: | ||
|
||
``` | ||
<bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource"> | ||
<property name="targetBeanName" value="businessObjectTarget"/> | ||
</bean> | ||
``` | ||
>在多线程或时多个类加载器环境中,不正确的使用ThreadLocals可能会导致严重的问题(可能引起内存泄漏)。应该考虑用其他类包装threadlocal,而不是直接使用。并且应该记得中正确为线程设置和取消(可以简单的调用`ThreadLocal.set(null)`)资源。无论什么情况下都要记住取消资源,否则可能会引发问题。Spring的ThreadLocal支持为你做了这一点,但你再使用其他没有正确的处理代码的ThreadLocal时,要考虑这点。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Spring AOP被设计成可拓展的。尽管内部使用的策略是拦截器实现的,它还可以支持任意的通知类型,除了开箱即用的拦截器外,还有around advice,before, throws advice和after returning advice。 | ||
`org.srpingframework.aop.framework.adapter`包是一个回调函数的包,用来在不改变核心框架的情况下,支持自定义的通知类型。唯一的约束是自定义的通知类型必须要是想`org.aopalliance.aop.Advice`标记接口。 | ||
请查阅`org.springframework.aop.framework.adapter`的文档来获取更多信息。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
请查看Spring实例程序来获得更多关于Spring AOP的应用: | ||
* JPetstore的默认配置说明了如何用`TransactionProxyFactoryBean`声明事物管理。 | ||
* JPetStore的`/attributes`目录说明了如何使用属性驱动的声明性事物管理。 |