Spring协调作用域不同步的bean


当两个 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>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值