假设降Web相关作用域的Bean注入到singleton或prototype的Bean中,我们当然希望它能够按照预定的方式工作,即应用者应该从指定的域中取得它对的引用。但如果没有进行一些额外的配置,我们将得到一个失望的结果。在这种情况下,需要Spring AOP出手相救:
非web相关作用域引用web相关作用域的Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=http://www.springframework.org/schema/beans
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:aop=http://www.springframework.org/schema/aop
xsi:schemaLocation="http://www.springframework,org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.rog/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean name="car" class="com.lxm.scope.Car" scope="request">
<aop:scope-proxy/>
</bean>
<bean id="boss class="com.lxm.scope,Boss">
<property name="car" ref="car"/>
</bean>
</beans>
car Bean 是request的作用域,它被迫singleton作用域的boss Bean引用。为了boss能够从适当作用中获取car Bean的引用,需要使用Spring AOP的语法为car Bean配置一个代理类。为了能够在配置文件中使用AOP的配置标签,我们需要在文档声明头中定义AOP命名空间。
当boss Bean在Web环境下,调用car Bean时,Spring AOP将启用动态代理智能地判断boss Bean位于哪个HTTP请求线程中,并从对应的HTTP请求线程域中获取对应的car Bean.
boss Bean的作用域是singleton,也就是说,在Spring容器中始终只有一个实例,而carBean的作用域为request,所以每个掉用到car Bean的那些HTTP请求都会创建一个car Bean .Spring通过动态代理技术,能够让boss Bean引用到对应HTTP请求的car Bean.
反过来,我们就很容易知道配置文件中添加<aop:scope-proxy/>后,注入到boss Bean中的car Bean已经不是原来的car Bean,而是car Bean 的动态代理对象了。这个动态代理是Car类的子类(或实现类,假设Car是接口),Spring在动态代理子类中加入一段逻辑以判断当前的boss 需要取得哪个HTTP请求相关的car Bean.
动态代理所添加的判断逻辑其实也很简单,就是判断当前boss位于哪个线程中哦,然后根据这个线程找到对应的HttppRequest,再从HttpRequest域中获取对应的car.因为Web容器的特性,一个HTTP请求一般情况下对应一个独立的线程。