spring 第5天不同作用域的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"));
		
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值