协调作用域不同步的bean
问题是;当一个singleton的bean依赖一个prototype的bean的时候,会产生不同步的现象
解决问题的方法
1:放弃部分依赖,当singleton的bean每次需要prototype的bean 的时候,主动向容器中访问新的bean. 这样会造成 与springAPI 严重耦合
2.利用方法注入 (我们用这种)
配置lookup-method 让spring帮我们实现
深入理解依赖配置关系
前面都是bean之间的依赖,下面讲的是,bean依赖bean之间的属性,方法返回值,field值
注入其他bean的属性值
将其他bean的属性值定义成一个bean
注入其他bean的Field值
注入其他bean的方法返回值
问题是;当一个singleton的bean依赖一个prototype的bean的时候,会产生不同步的现象
解决问题的方法
1:放弃部分依赖,当singleton的bean每次需要prototype的bean 的时候,主动向容器中访问新的bean. 这样会造成 与springAPI 严重耦合
2.利用方法注入 (我们用这种)
//singleton bean
package cn.sh.springmvc.model;
import cn.sh.springmvc.model.interfaces.Axe;
import cn.sh.springmvc.model.interfaces.Person;
/**
* 不同作用于的 依赖与协同
* 采用方法注入新的Bean ,解决:singleton Bean中使用个prototypeBean 的问题
* @author Bin
*
*/
public abstract class Japanese implements Person {
//定义一个方法 让spring 跟我们实现,这样就能保证每次都是新的对象
public abstract Axe getAxe();
@Override
public void useAxe() {
System.out.println("正在使用"+getAxe()+"劈柴");
System.out.println(getAxe().chop());
}
}
//prototype bean
package cn.sh.springmvc.model;
import cn.sh.springmvc.model.interfaces.Axe;
public class StoneAxe implements Axe {
private String name;
public StoneAxe() {
System.out.println("石头初始化StoneAxe");
}
@Override
public String chop() {
// TODO Auto-generated method stub
return name+"石斧看柴慢";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
配置lookup-method 让spring帮我们实现
<!-- 不同作用于的协同工作 --> <bean id="stoneAxe1" class="cn.sh.springmvc.model.StoneAxe" scope="prototype"> <property name="name" value="磨过"/> </bean> <bean id="japanese" class="cn.sh.springmvc.model.Japanese" scope="singleton"> <lookup-method name="getAxe" bean="stoneAxe1"/> </bean>
//测试 不同作用域的Bean相互依赖后出现的工作不协调问题
@Test
public void test17() {
AbstractApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
Japanese p=act.getBean("japanese",Japanese.class);
p.useAxe();
p.useAxe();
System.out.println(p.getAxe()==p.getAxe());
}
深入理解依赖配置关系
前面都是bean之间的依赖,下面讲的是,bean依赖bean之间的属性,方法返回值,field值
在spring配置文件中使用xml元素进行配置,实际上是让spring执行相应的java代码
例如:
1.使用<bean>元素,就是让spring执行无参数构造函数
2.使用<property> 就是让spring执行setter方法
但是java程序还有可能还有其他语句,调用getting,调用普通方法,访问类或者对象的file,spring也为这种语句提供利配置的语法
3.调用getter方法:使用 PropertyPathFactoryBean
4.访问类或对象的Field值,使用FieldRetrievingFactoryBean
5.调用普通方法:使用MethodInvokingFactoryBean
由此可见,spring可以然我们不写java代码就可以实现java编程,只要使用合适XML 语法进行配置,spring就可通过反射执行任意的底层java代码.
注入其他bean的属性值
<!-- 注入其他Bean的属性 --> <bean id="chinese1" class="cn.sh.springmvc.model.Chinese"> <property name="axe" ref="stoneAxe"/> </bean> <!-- Bean 之间的属性依赖 --> <bean id="chinese2" class="cn.sh.springmvc.model.Chinese"> <property name="axe"> <!--注意这里,并不是bean的ID,而是属性的表达式 --> <bean id="chinese1.axe" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/> </property> </bean>
将其他bean的属性值定义成一个bean
<!-- 指定一个Bean实例的属性定义为一个 Bean --> <bean id="pro_stoneAxe" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese1"/> <property name="propertyPath" value="axe"/> </bean> <bean id="stone_name" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese1"/> <property name="propertyPath" value="axe.name"/> </bean> <bean id="chinese_list" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese"/> <property name="propertyPath" value="schools"/> </bean> <bean id="chinese_list_ele" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese"/> <property name="propertyPath" value="schools[0]"/> </bean> <bean id="chinese_map_ele" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese"/> <property name="propertyPath" value="entrySet[0]"/> </bean> <!-- 注意有些集合不是 有序的,如果集合没有采用泛型定义,注意返回的类型 --> <bean id="chinese_set_ele_str" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese"/> <property name="propertyPath" value="axes[0]"/> </bean> <bean id="chinese_set_ele_obj" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetBeanName" value="chinese"/> <property name="propertyPath" value="axes[1]"/> </bean> <!-- 采用嵌套bean --> <bean id="new_stone_name" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"> <property name="targetObject"> <bean class="cn.sh.springmvc.model.SteelAxe"> <property name="name" value="打磨过的"/> </bean> </property> <property name="propertyPath" value="name"/> </bean>
//测试 Bean实例属性之间的依赖,以及将一个实例Bean的属性定义成一个Bean
//注意 org.springframework.beans.factory.config.PropertyPathFactoryBean
//如果将对象的属性定义成Bean 的时候,要指定targetBeanName 和 propertyPath 两个属性
@Test
public void test18() {
AbstractApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
//属性之间的传递
Chinese c2=act.getBean("chinese2",Chinese.class);
System.out.println(c2.getAxe().chop());
//属性的对象
Axe a=act.getBean("pro_stoneAxe",Axe.class);
System.out.println(a.chop());
//属性对象的属性
String name=act.getBean("stone_name",String.class);
System.out.println(name);
//对象的 list
List<String> schools=act.getBean("chinese_list",List.class);
System.out.println(schools.get(0));
//对象的 list 中的元素
String schools_Name=act.getBean("chinese_list_ele",String.class);
System.out.println(schools_Name);
//对象的 map 中的元素
/*Set<Map.Entry<String,Object>> set=act.getBean("chinese_map_ele",Set.class);
for(Iterator<Map.Entry<String,Object>> it=set.iterator();it.hasNext();){
Map.Entry<String,Object> entry=it.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}*/
Map.Entry<String,Object> entry=act.getBean("chinese_map_ele",Map.Entry.class);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
String set1=act.getBean("chinese_set_ele_str",String.class);
System.out.println(set1);
SteelAxe obj=act.getBean("chinese_set_ele_obj",SteelAxe.class);
System.out.println(obj.chop());
//使用内嵌Bean的属性
String stone_Name=act.getBean("new_stone_name",String.class);
System.out.println(stone_Name);
}
注入其他bean的Field值
<!-- 注入其他Bean的Field的值 --> <!-- 将 java.sql.Connection.TRANSACTION_SERIALIZABLE属性值给 user的age属性--> <bean id="user1" class="cn.sh.springmvc.model.User"> <property name="age"> <bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/> </property> </bean> <!--将 java.sql.Connection.TRANSACTION_SERIALIZABLE 定义成一个bean --> <bean id="theAge" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"> <property name="targetClass" value="java.sql.Connection"/> <property name="targetField" value="TRANSACTION_SERIALIZABLE"/> </bean> <!-- 如果 字段为静态 的,还可以简写 --> <bean id="theAge1" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"> <property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/> </bean>
//测试 注入其他Bean的Field字段值
//FieldRetrievingFactoryBean targetClass targetField staticField
@Test
public void test19() {
AbstractApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
User u= act.getBean("user1",User.class);
System.out.println(u.getAge());
Integer level=act.getBean("theAge",Integer.class);
System.out.println(level);
Integer level1=act.getBean("theAge1",Integer.class);
System.out.println(level1);
}
注入其他bean的方法返回值
<!-- 注入 其他Bean的方法返回值 --> <bean id="valueGenerate" class="cn.sh.springmvc.model.ValueGenerator"/> <bean id="user2" class="cn.sh.springmvc.model.User"> <property name="age"> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject" ref="valueGenerate"/> <property name="targetMethod" value="getValue"/> </bean> </property> </bean> <!-- 如果是静态方法 --> <bean id="user3" class="cn.sh.springmvc.model.User"> <property name="age"> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <!-- 如果是静态方法.可以不用 targetObject --> <property name="targetClass" value="cn.sh.springmvc.model.ValueGenerator"/> <property name="targetMethod" value="getStaticVal"/> </bean> </property> </bean> <!-- 如果方法方法存在重载 指定参数--> <bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="java.lang.System"/> <property name="targetMethod" value="getProperties"/> </bean> <bean id="java_version" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="java.lang.System"/> <property name="targetMethod" value="getProperty"/> <property name="arguments"> <list> <value>java.version</value> </list> </property> </bean> <bean id="mth_stoneAxe_sft" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="cn.sh.springmvc_java.factory.AxeFactory"/> <property name="targetMethod" value="getAxe"/> <property name="arguments"> <list><value>stone</value></list> </property> </bean> <!-- 如果是静态的method 可以省略 targetClass --> <bean id="mth_steelAxe_sft" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="cn.sh.springmvc_java.factory.AxeFactory.getAxe"/> <property name="arguments"> <list><value>steel</value></list> </property> </bean> <!-- 使用嵌套bean --> <bean id="mth_people_sft" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject"> <bean class="cn.sh.springmvc_java.factory.PeopleFactory"/> </property> <property name="targetMethod" value="getPeople"/> <property name="arguments"> <list><value>chin</value></list> </property> </bean>
//测试 注入其他Bean的方法返回值
//MethodInvokingFactoryBean targetClass targetMethod
@Test
public void test20() {
AbstractApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
User u= act.getBean("user2",User.class);
System.out.println(u.getAge());
User u1=act.getBean("user3",User.class);
System.out.println(u1.getAge());
Properties syspro=act.getBean("sysProps",Properties.class);
System.out.println(syspro.getProperty("java.version"));
System.out.println(act.getBean("java_version"));
System.out.println(System.getProperty("java.version"));
Axe saxe=act.getBean("mth_stoneAxe_sft",Axe.class);
System.out.println(saxe.chop());
Axe saxe1=act.getBean("mth_steelAxe_sft",Axe.class);
System.out.println(saxe1.chop());
People p=act.getBean("mth_people_sft",People.class);
System.out.println(p.sayHello("admin"));
}