Spring IOC

Bean元数据信息在Spring容器中对应物是由一个个BeanDefinition形成的Bean注册表,

Bean配置信息定义了Bean的实现以及依赖关系

  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <beans   xmlns="http://www.springframework.org/schema/beans"   
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://www.springframework.org/schema/beans   
  5.          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
  6.      <bean id="car" name="#car1" class="com.baobaotao.simple.Car"></bean>    
  7.      <bean id="boss" class="com.baobaotao.simple.Boss"></bean>  
  8. </beans>  
<?xml version="1.0" encoding="UTF-8" ?>
<beans   xmlns="http://www.springframework.org/schema/beans" 
	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     <bean id="car" name="#car1" class="com.baobaotao.simple.Car"></bean>  
     <bean id="boss" class="com.baobaotao.simple.Boss"></bean>
</beans>

Bean的名字:

id作为Bean的名称,在IOC容器中必须唯一,由字母开头,后面可以是a-zA-Z0-9-.等

Bean也可以使用name进行命名,name没有字符上的限制,几乎可以使用任意字符,不过最好不要使用中文字符,name可以重复,getBean(beanName)时返回最后的那个bean

name可以写多个逗号用,隔开,例如name="p,q",id不可以

如果id和name都没有指定,name默认使用类的全称作为Bean名字,<bean id="boss" class="com.baobaotao.simple.Boss"></bean>要使用getBean("com.baobaotao.simple.Boss");来获得,如果出现下面的情况:

同一个容器中:

<bean class="com.baobaotao.simple.Boss"></bean> 

<bean  class="com.baobaotao.simple.Boss"></bean>

<bean  class="com.baobaotao.simple.Boss"></bean>

第一个通过getBean("com.baobaotao.simple.Boss");或者getBean("com.baobaotao.simple.Boss#0");获得第二个通过getBean("com.baobaotao.simple.Boss#1");获得,第三个通过getBean("com.baobaotao.simple.Boss#2");获得


依赖注入:


属性注入:

  1. <bean id="car" class="com.baobaotao.attr.Car" lazy-init="default">  
  2.         <property name="brand">  
  3.             <value>  
  4.                 <![CDATA[红旗&CA72]]>  
  5.             </value>  
  6.         </property>  
  7.         <property name="maxSpeed">  
  8.             <value>200</value>  
  9.         </property>  
  10.         <property name="price" value="2000.00" />  
  11.     </bean>  
<bean id="car" class="com.baobaotao.attr.Car" lazy-init="default">
		<property name="brand">
			<value>
				<![CDATA[红旗&CA72]]>
			</value>
		</property>
		<property name="maxSpeed">
			<value>200</value>
		</property>
		<property name="price" value="2000.00" />
	</bean>
属性名以小写开头,应符合java命名规范,如果出现特殊情况,也要保持属性前两个字母,要么全部大写要么全部小写

  1. <property name="favorites">  
  2.     <set>  
  3.         <value>看报</value>  
  4.         <value>赛车</value>  
  5.         <value>高尔夫</value>  
  6.     </set>  
  7. </property>  
		<property name="favorites">
			<set>
				<value>看报</value>
				<value>赛车</value>
				<value>高尔夫</value>
			</set>
		</property>

  1. <list>  
  2.                 <value>看报</value>  
  3.                 <value>赛车</value>  
  4.                 <value>高尔夫</value>  
  5.         </list>  
<list>
				<value>看报</value>
				<value>赛车</value>
				<value>高尔夫</value>
		</list>

 

  1. <list>  
  2.    <ref bean="usera"/>  
  3.    <ref bean="userb"/>  
  4.    <ref bean="userc"/>  
  5. </list>  
<list>
   <ref bean="usera"/>
   <ref bean="userb"/>
   <ref bean="userc"/>
</list>


  1. <array>  
  2.       <value>看报</value>  
  3.        <value>赛车</value>  
  4. </array>  
<array>
      <value>看报</value>
       <value>赛车</value>
</array>


 

  1. <map>  
  2.                 <entry >  
  3.                     <key>  
  4.                         <value>AM</value>  
  5.                     </key>  
  6.                     <value>会见客户</value>  
  7.                 </entry>  
  8.                 <entry>  
  9.                     <key>  
  10.                         <value>PM</value>  
  11.                     </key>  
  12.                     <value>公司内部会议</value>  
  13.                 </entry>  
  14.             </map>  
<map>
				<entry >
					<key>
						<value>AM</value>
					</key>
					<value>会见客户</value>
				</entry>
				<entry>
					<key>
						<value>PM</value>
					</key>
					<value>公司内部会议</value>
				</entry>
			</map>

  1. <props>  
  2.                 <prop key="jobMail">john-office@baobaotao.com</prop>  
  3.                 <prop key="lifeMail">john-life@baobaotao.com</prop>  
  4.             </props>  
<props>
				<prop key="jobMail">john-office@baobaotao.com</prop>
				<prop key="lifeMail">john-life@baobaotao.com</prop>
			</props>

  1. <property name="car">  
  2.             <ref local="car" /> 指向另一个bean的id  
  3.         </property>  
<property name="car">
			<ref local="car" /> 指向另一个bean的id
		</property>
<ref>元素可通过三个属性引用其他容器中的Bean:

bean:同一个容器或者父容器中的Bean(常见)

local:同一配置文件中定义的bean

parent:父容器中的bean

父子容器允许有相同id的bean,子容器可以访问父容器中的bean,父容器却不能访问子容器中的bean,我们自己很少写父子容器,下面是父子容器的简单代码:

  1. ClassPathXmlApplicationContext parentFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"});  
  2. ClassPathXmlApplicationContext childFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"},parentFactory);  
  3. childFactory.getBean("bean");  
ClassPathXmlApplicationContext parentFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"});
ClassPathXmlApplicationContext childFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"},parentFactory);
childFactory.getBean("bean");

  1. <bean id="sportsCar" class="com.baobaotao.attr.SportsCar">  
  2.     <property name="brand">  
  3.         <bean id="car.brand"  
  4.             class="org.springframework.beans.factory.config.PropertyPathFactoryBean">  
  5.         </bean>  
  6.     </property>  
  7. </bean>  
	<bean id="sportsCar" class="com.baobaotao.attr.SportsCar">
		<property name="brand">
			<bean id="car.brand"
				class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
			</bean>
		</property>
	</bean>

上面的是内部bean,虽然提供了id,但是其他bean都不能使用它,name,id,scope属性都会被忽略,这里scope默认为prototype,如果sportsCar是prototype类型的话,每次得到一个"新"的sportsCar时,都会调用一次brand对应的bean的构造方法,如果是在外面定义的bean,scope默认值就是singleton的,上面定义的sportsCar就是singleton类型的

  1. <property name="IDCode"><value></value></property> 值是空字符串  
			<property name="IDCode"><value></value></property> 值是空字符串
  1. <property name="IDCode"><null/></property> 值是null  
  <property name="IDCode"><null/></property> 值是null
  1. <property name="car.name"><null/></property>   级联属性 会调用 .getCar().setName(null); 如果car不存在为null,就会出错  
<property name="car.name"><null/></property>   级联属性 会调用 .getCar().setName(null); 如果car不存在为null,就会出错
如果子bean继承了父bean的同名集合元素,可以把父子合并:

  1. <bean id="parentBoss" abstract="true"  
  2.         class="com.baobaotao.attr.Boss">  
  3.         <property name="favorites">  
  4.             <set>  
  5.                 <value>看报</value>  
  6.                 <value>赛车</value>  
  7.                 <value>高尔夫</value>  
  8.             </set>  
  9.         </property>  
  10.     </bean>  
  11.     <bean id="childBoss" parent="parentBoss">  
  12.         <property name="favorites">  
  13.             <set merge="true">  
  14.                 <value>爬山</value>  
  15.                 <value>游泳</value>  
  16.             </set>  
  17.         </property>  
  18.     </bean>     
<bean id="parentBoss" abstract="true"
		class="com.baobaotao.attr.Boss">
		<property name="favorites">
			<set>
				<value>看报</value>
				<value>赛车</value>
				<value>高尔夫</value>
			</set>
		</property>
	</bean>
	<bean id="childBoss" parent="parentBoss">
		<property name="favorites">
			<set merge="true">
				<value>爬山</value>
				<value>游泳</value>
			</set>
		</property>
	</bean>	

为了简化操作可以使用p命名空间,p:属性名="xxx"   p:属性名_ref="xxx",例如:

  1. <bean id="car" class="com.baobaotao.ditype.Car"  
  2.    p:brand="红旗&CA72"  
  3.    p:maxSpeed="200"  
  4.    p:price="20000.00"/>  
  5. <bean id="boss" class="com.baobaotao.ditype.Boss"  
  6. p:car-ref="car"/>  
   <bean id="car" class="com.baobaotao.ditype.Car"
      p:brand="红旗&CA72"
      p:maxSpeed="200"
      p:price="20000.00"/>
   <bean id="boss" class="com.baobaotao.ditype.Boss"
	  p:car-ref="car"/>

如果希望配置集合类型的bean,那么可以使用util命名空间

  1. <util:list id="favoriteList1" list-class="java.util.LinkedList">  
  2.         <value>看报</value>  
  3.         <value>赛车</value>  
  4.         <value>高尔夫</value>  
  5.     </util:list>  
<util:list id="favoriteList1" list-class="java.util.LinkedList">
		<value>看报</value>
		<value>赛车</value>
		<value>高尔夫</value>
	</util:list>
  1. <util:set id="favoriteSet1"  >  
  2.         <value>看报</value>  
  3.         <value>赛车</value>  
  4.         <value>高尔夫</value>  
  5. </util:set>  
<util:set id="favoriteSet1"  >
		<value>看报</value>
		<value>赛车</value>
		<value>高尔夫</value>
</util:set>
  1. <util:map id="emails1" >  
  2.         <entry key="AM" value="会见客户" />  
  3.         <entry key="PM" value="公司内部会议" />  
  4.     </util:map>  
<util:map id="emails1" >
		<entry key="AM" value="会见客户" />
		<entry key="PM" value="公司内部会议" />
	</util:map>
  1. <util:properties id="emailProps1"  
  2.         location="classpath:com/baobaotao/fb/mails.properties" />  
<util:properties id="emailProps1"
		location="classpath:com/baobaotao/fb/mails.properties" />

当然该util类还有其他用处,例如:

  1. <property name="brand">  
  2.             <util:constant  
  3.                 static-field="com.baobaotao.fb.CarBrandType.HONG_QI" />  
  4.         </property>  
<property name="brand">
			<util:constant
				static-field="com.baobaotao.fb.CarBrandType.HONG_QI" />
		</property>
  1. <property name="brand">  
  2.             <util:property-path path="boss.car.brand"/> 找到id为boss的bean取出car中的brand属性  
  3.         </property>  
<property name="brand">
			<util:property-path path="boss.car.brand"/> 找到id为boss的bean取出car中的brand属性
		</property>




构造方法注入:

按类型:

  1. <bean name="constructorBean" class="bean.ConstructorBean">   
  2. <constructor-arg type="java.lang.String" value="1"/>   
  3. <constructor-arg type="java.lang.Integer" value="2"/>   
  4. </bean>   
<bean name="constructorBean" class="bean.ConstructorBean"> 
<constructor-arg type="java.lang.String" value="1"/> 
<constructor-arg type="java.lang.Integer" value="2"/> 
</bean> 
如果构造方法中有两个相同的类型就出问题了,按索引值:

  1. <bean name="constructorBean" class="bean.ConstructorBean">   
  2. <constructor-arg index="0" value="1"/>   
  3. <constructor-arg index="1" value="2"/>   
  4. </bean>   
<bean name="constructorBean" class="bean.ConstructorBean"> 
<constructor-arg index="0" value="1"/> 
<constructor-arg index="1" value="2"/> 
</bean> 

两者联合使用也可以:

  1. <bean name="constructorBean" class="bean.ConstructorBean">   
  2. <constructor-arg index="0" type="java.lang.String" value="1"/>   
  3. <constructor-arg index="1" type="int" value="2"/>   
  4. </bean>   
<bean name="constructorBean" class="bean.ConstructorBean"> 
<constructor-arg index="0" type="java.lang.String" value="1"/> 
<constructor-arg index="1" type="int" value="2"/> 
</bean> 

使用构造方法注入时有可能出现循环依赖,比如 Bean1中有Bean2属性,Bean2中也有Bean1属性,两者都使用构造注入就出现了循环依赖问题


工厂方法注入:(参考:http://550516671-qq-com.iteye.com/blog/803999)

非静态方法:

  1. public class CarFactory {     
  2.     
  3.     public Car createHongQiCar(){     
  4.         Car car = new Car();     
  5.         car.setName("红旗");     
  6.         car.setSpeed("200");     
  7.         return car;     
  8.     }     
  9.          
  10. }    
public class CarFactory {   
  
    public Car createHongQiCar(){   
        Car car = new Car();   
        car.setName("红旗");   
        car.setSpeed("200");   
        return car;   
    }   
       
}  
  1. <bean id="carFactory" class="com.lbx.factory.CarFactory"></bean>    
  2. <bean id="car" factory-bean="carFactory" factory-method="createHongQiCar"></bean>  
<bean id="carFactory" class="com.lbx.factory.CarFactory"></bean>  
<bean id="car" factory-bean="carFactory" factory-method="createHongQiCar"></bean>

静态方法:

 

  1. public class CarFactory2 {     
  2.     
  3.     public static Car createHongQiCar(){     
  4.         Car car = new Car();     
  5.         car.setName("红旗");     
  6.         car.setSpeed("200");     
  7.         return car;     
  8.     }     
  9.          
  10. }    
public class CarFactory2 {   
  
    public static Car createHongQiCar(){   
        Car car = new Car();   
        car.setName("红旗");   
        car.setSpeed("200");   
        return car;   
    }   
       
}  

  1. <bean id="car" class="com.lbx.factory.CarFactory2" factory-method="createHongQiCar"></bean>    
<bean id="car" class="com.lbx.factory.CarFactory2" factory-method="createHongQiCar"></bean>  

 


Bean的作用域通过scope属性来指定,值如下:(参考:http://blog.csdn.net/mastermind/article/details/1932787)

singleton

当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。

prototype
prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的 getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)

request
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效

session
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效

global session
global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用

自定义bean装配作用域
在spring2.0中作用域是可以任意扩展的,你可以自定义作用域,甚至你也可以重新定义已有的作用域(但是你不能覆盖singleton和prototype),spring的作用域由接口org.springframework.beans.factory.config.Scope来定义,自定义自己的作用域只要实现该接口即可

 

bean之间的依赖关系可以自动装配,在beans中可以配置属性default-autowire(全局对所有bean生效),在bean中设置autowire来实现。值如下:

no:通过ref元素指定依赖

byName:在容器中寻找和需要自动装配的属性名相同的Bean(或ID),如果没有找到相符的Bean,该属性就没有被装配上.

byType:在容器中寻找一个与需要自动装配的属性类型相同的Bean;如果没有找到相符的Bean,该属性就没有被装配上.

Constructor:在容器中查找与需要自动装配的Bean的构造方法参数一致的一个或者多个Bean,如果存在不确定的Bean或构造方法,容器会抛出异常org.springframework.beans.factory.UnsatisfiedDependencyException.

Autodetect:使用constructor或byType来自动装配。如果提供了默认的无参构造,就使用byType

 

 

方法注入:

让bean实现BeanFactoryAware,在方法中写:return (Car)factory.getBean("car");用在单例的bean中每次获取某属性时都要求是prototype类型的对象

lookup注入:bean中的某方法返回值并不是执行该方法得到的结果,而是容器中的某个bean,这里是通过为bean动态创建子类或实现类的方式实现的,例如

  1.  <bean name="userManager"  class="research.spring.beanfactory.ch2.UserManager">  
  2.        <lookup-method name="getUserDao" bean="userDao" />  
  3. </bean>  
 <bean name="userManager"  class="research.spring.beanfactory.ch2.UserManager">
       <lookup-method name="getUserDao" bean="userDao" />
</bean>

这里如果调用userManager中的getUserDao会返回userDao,无论UserManager中getUserDao有无实现

方法替换:

一个bean中的方法用另一个bean中相同签名的方法替换掉,例如:

  1. <bean id="boss2" class="com.baobaotao.injectfun.Boss2"/>  
  2. <bean id="boss1" class="com.baobaotao.injectfun.Boss1">  
  3.    <replaced-method name="getCar" replacer="boss2"></replaced-method>  
  4. t;/bean>  
  <bean id="boss2" class="com.baobaotao.injectfun.Boss2"/>
  <bean id="boss1" class="com.baobaotao.injectfun.Boss1">
     <replaced-method name="getCar" replacer="boss2"></replaced-method>
</bean>


bean之间的关系:

继承:

父bean一般设置abstract=“true”表示只是为了代码被复用,子bean写属性parent=“parentbeanid”,这样子bean就可复制了父bean的配置信息

依赖:

在bean中写depends-on="beana" 那么保证在实例化当前bean时一定有了被依赖的bean了;即使不写依赖关系spring也会自动处理,这个属性主要在代码中依赖很不明显的情况下使用

引用:

把之前的ref标签改为idref标签,这样如果写错了id值,不是在运行时用到再报错,而是在容器启动时就报错了

 

如果需要一个配置文件包含其他配置文件,可以使用<import resource="classpath:com/auscend/beans.xml"/>

在bean标签中属性init-method="init" 定义实例化bean之后调用的方法, destroy-method="destory"定义要销毁bean之前要调用的方法,这两个方法都是定义在bean内部的方法,要注意如果是prototype的bean,容器只负责创建,不负责销毁。

以上都是在xml中使用,如果要用注解的话,参考另一篇:spring IOC annotation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值