当两个
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.0的
spring-core-*.jar包中已经集成了
cglib类库,因此无须额外添加
cglib的
JAR包了。
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>