Spring IoC容器不仅为你初始化对象,并且会为你关联那些互相协作的bean或者依赖,如果你想将一个生命周期为HTTP request的bean注入到另一bean中,你必须在这个bean中注入一个AOP代理,这个代理具有和这个bean相同的接口,当调用这些API的时候,实际会委托调用真实的对象。至于为什么要这么做,可以看下下面的例子。
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- an HTTP Session-scoped bean exposed as a proxy --> <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> <!-- instructs the container to proxy the surrounding bean --> <aop:scoped-proxy/> </bean> <!-- a singleton-scoped bean injected with a proxy to the above bean --> <bean id="userService" class="com.foo.SimpleUserService"> <!-- a reference to the proxied userPreferences bean --> <property name="userPreferences" ref="userPreferences"/> </bean> </beans>
为了创建这个代理,你在bean中插入了这么一个元素<aop:scoped-proxy/>,(如果你选择使用基于类的代理,你需要在你的CLASSPATH里加入CGLIB jar包,默认选择CGLIB),为什么除了singleton,和prototype生命周期的bean都需要<aop:scoped-proxy/>呢?那让我们回过头来看看prototype和前面提到的session的scope(注意:以下这段配置是不完整的,只作说明用)。
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> <bean id="userManager" class="com.foo.UserManager"> <property name="userPreferences" ref="userPreferences"/> </bean>
因此,当你要注入的bean的scope是request,session或globalSession时,正确完整的写法应该是下面这样的:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> <aop:scoped-proxy/> </bean> <bean id="userManager" class="com.foo.UserManager"> <property name="userPreferences" ref="userPreferences"/> </bean>