Spring——使用cglib更新长生命周期中引用的短生命周期bean

在长生命周期的bean引用短生命周期bean时,会有一个问题。 比如singleton 类依赖了prototype类,容器会在singleton 类初始化时,就根据依赖关系将prototype类注入。以后的每一次调用singleton bean都是同一个对象,里面的prototype bean也是最初注入的那个,容器再也不会为singleton bean产生新的prototype bean。
我们可以通过在短生命周期的bean定义中加入<aop:scoped-proxy/>轻松解决这个问题。

但是,有些业务情况要求在增加新的bean时,不允许改动以前的bean定义和旧的代码。简单的说:被调用者(短生命周期bean)不允许修改,只能修改调用者(新增的长生命周期bean),所以这篇就讲讲如何利用Lookup达到我们的要求。

Lookup方法的工作机制是使用cglib在产生字节码这个阶段生成一个代理类,因此我们先要在工程中引入cglib组件。

程序代码如下:

接口:

package twm.spring.lookup;
public interface UserSession {
    Object getInstance();
}

接口的实现类:

package twm.spring.lookup;
public class UserSessionImpl implements UserSession{
    @Override
    public Object getInstance() {
        return this;
    }
}

业务类ServiceBean依赖UserSession:
因为setUserSession只是声明,并没有实现,所以是个抽象方法。声明这个抽象方法是为了让Lookup注入代理对象的。
当然也可以不声明为抽象方法(并不是强制要求),不过最终Lookup会覆盖原方法里的实现内容。

package twm.spring.lookup;
public abstract class ServiceBean {
    UserSession userSession;
    //原来的setter注入不要了
    //public void setUserSession(UserSession userSession) {
    //  this.userSession = userSession;
    //}
    public Object Perform(){
        this.userSession=setUserSession();
        return this.userSession.getInstance();
    }
    //抽象方法,由lookup-method注入具体bean
    abstract UserSession setUserSession();
}

beans.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:c="http://www.springframework.org/schema/c" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

<bean id="usession" class="twm.spring.lookup.UserSessionImpl" scope="prototype">
</bean> 

<bean id="servicebean" class="twm.spring.lookup.ServiceBean">
    <!-- <property name="UserSession" ref="usession"/> -->
    <!-- name是类中返回代理对象的方法名,bean是lookup-method要代理的对象 -->
    <lookup-method name="setUserSession" bean="usession"/>
</bean> 
</beans>

调用代码:

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ServiceBean us=ctx.getBean("servicebean",ServiceBean.class);
System.out.println(us.Perform());
System.out.println(us.Perform());

运行输出:

twm.spring.lookup.UserSessionImpl@13838e4 
twm.spring.lookup.UserSessionImpl@1f34a6

打印出的两个usession对象的地址不一样,说明我们实现了每次调用都能获得新的短生命周期的对象。
<lookup-method>标签中的name属性就是servicebean Bean中获取UserSession实例的方法,即:setUserSession()方法;bean属性是要注入的bean对象,这里是usession。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值