Spring协调作用域不同步的bean

来源:互联网 发布:大唐绍兴江滨热电知乎 编辑:程序博客网 时间:2024/05/13 20:23

当两个singleton作用域的Bean存在依赖关系时,或者当prototype作用域的bean依赖singleton作用域的Bean时,使用Spring提供的依赖注入进行管理即可。


singleton作用域的Bean只有一次初始化的机会,它的依赖关系也只有在初始化阶段被设置,当singleton作用域的Bean依赖prototype作用域的Bean时,Spring容器会在初始化singleton作用域的Bean之前,先创建被依赖的prototype Bean,然后才初始化singleton Bean,并将prototype Bean注入singleton Bean,这会导致以后无论何时通过singleton Bean去访问prototype Bean时,得到的永远是最初那个prototype Bean——这样就相当于singleton Bean把它所依赖的prototype Bean变成了singleton行为。

singleton作用域的Bean只有一次初始化的机会,它的依赖关系也只有在初始化阶段被设置,当singleton作用域的Bean依赖prototype作用域的Bean时,Spring容器会在初始化singleton作用域的Bean之前,先创建被依赖的prototype Bean,然后才初始化singleton Bean,并将prototype Bean注入singleton Bean,这会导致以后无论何时通过singleton Bean去访问prototype Bean时,得到的永远是最初那个prototype Bean——这样就相当于singleton Bean把它所依赖的prototype Bean变成了singleton行为。


放弃依赖注入:singleton作用域的Bean每次需要prototype作用域的Bean时,主动向容器请求新的Bean实例,即可保证每次注入prototype Bean实例都是最新的实例

利用方法注入:
第一种方法显然不是一个好的做法,代码主动请求新的Bean实例,必然导致程序代码与Spring API解耦,造成代码污染。在通常情况下,建议采用第二种方法,使用方法注入。

----------------------------------------------

方法注入通常使用lookup-method方法注入,使用lookup-method方法注入可以让Spring容器重写容器中Bean的抽象或具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个non-singleton Bean(尽管也可以是一个singleton)。Spring通过使用JDK动态代理或cglib库修改客户端的二进制码,从而实现上述要求。为了使用lookup-method方法注入,大致需要如下两步:

将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean

在<bean.../>元素中添加<lookup-method.../>子元素让Spring为调用者Bean的实现类实现指定的抽象方法。<lookup-method.../>子元素告诉Spring需要实现哪个抽象方法。Spring为抽象方法提供实现体之后,这个方法就会变成具体方法,这个类也就变成了具体类,接下来Spring就可以创建该Bean的实例了。

使用<lookup-method.../>元素需要指定如下两个属性:
name:指定需要让Spring实现的方法
bean:指定Spring实现该方法的返回值
注意:Spring4.0spring-core-*.jar包中已经集成了cglib类库,因此无须额外添加cglibJAR包了。

具体代码:

service层:

package com.cn.service;


public interface Axe {

  public String chop();

}


package com.cn.service;

public interface Person {
  public void useAxe();
}

service实现类(service.imp):

package com.cn.service.imp;

import com.cn.service.Axe;
import com.cn.service.Person;

public abstract class Chinese implements Person {
  private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public abstract Axe getAxe();

public void useAxe() {
System.out.println("我是火星人名字叫:" + name+",我拿着"+getAxe()+"去杀敌");
System.out.println(getAxe().chop());;
}

}

package com.cn.service.imp;

import com.cn.service.Axe;

public class SteelAxe implements Axe {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String chop() {
// TODO Auto-generated method stub
return "这是一把斧头名字叫:" + name+",我是一把远古神器";
}
}

测试类:
package com.cn.Text;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.cn.service.Person;

public class BeanText {
public static void main(String[] args) {
ApplicationContext acContext=new ClassPathXmlApplicationContext("bean.xml");
Person p1=acContext.getBean("chinese",Person.class);
Person p2=acContext.getBean("chinese",Person.class);
        p1.useAxe();
        p2.useAxe();
}

bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

<bean id="chinese" class="com.cn.service.imp.Chinese" scope="singleton">
<!-- name:指定需要让Spring实现的方法 bean:指定Spring实现该方法的返回值的实现类-->
<lookup-method name="getAxe" bean="steelAxe" />
<property name="name" value="帝天"></property>
</bean>
<bean id="steelAxe" class="com.cn.service.imp.SteelAxe" scope="prototype">
<property name="name" value="刑天"/>
</bean>



原创粉丝点击