Spring IOC 详解
来源:互联网 发布:js 拆分字符串为数组 编辑:程序博客网 时间:2024/05/17 11:58
Bean元数据信息在Spring容器中对应物是由一个个BeanDefinition形成的Bean注册表,
Bean配置信息定义了Bean的实现以及依赖关系
- <?xmlversion="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">
- <beanid="car"name="#car1"class="com.baobaotao.simple.Car"></bean>
- <beanid="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");获得
依赖注入:
属性注入:
- <beanid="car"class="com.baobaotao.attr.Car"lazy-init="default">
- <propertyname="brand">
- <value>
- <![CDATA[红旗&CA72]]>
- </value>
- </property>
- <propertyname="maxSpeed">
- <value>200</value>
- </property>
- <propertyname="price"value="2000.00"/>
- </bean>
- <propertyname="favorites">
- <set>
- <value>看报</value>
- <value>赛车</value>
- <value>高尔夫</value>
- </set>
- </property>
- <list>
- <value>看报</value>
- <value>赛车</value>
- <value>高尔夫</value>
- </list>
- <list>
- <ref bean="usera"/>
- <refbean="userb"/>
- <ref bean="userc"/>
- </list>
- <array>
- <value>看报</value>
- <value>赛车</value>
- </array>
- <map>
- <entry>
- <key>
- <value>AM</value>
- </key>
- <value>会见客户</value>
- </entry>
- <entry>
- <key>
- <value>PM</value>
- </key>
- <value>公司内部会议</value>
- </entry>
- </map>
- <props>
- <propkey="jobMail">john-office@baobaotao.com</prop>
- <propkey="lifeMail">john-life@baobaotao.com</prop>
- </props>
- <propertyname="car">
- <reflocal="car"/> 指向另一个bean的id
- </property>
bean:同一个容器或者父容器中的Bean(常见)
local:同一配置文件中定义的bean
parent:父容器中的bean
父子容器允许有相同id的bean,子容器可以访问父容器中的bean,父容器却不能访问子容器中的bean,我们自己很少写父子容器,下面是父子容器的简单代码:
- ClassPathXmlApplicationContext parentFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"});
- ClassPathXmlApplicationContext childFactory=new ClassPathXmlApplicationContext(new String[]{"parent.xml"},parentFactory);
- childFactory.getBean("bean");
- <beanid="sportsCar"class="com.baobaotao.attr.SportsCar">
- <propertyname="brand">
- <beanid="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类型的
- <propertyname="IDCode"><value></value></property> 值是空字符串
- <propertyname="IDCode"><null/></property> 值是null
- <propertyname="car.name"><null/></property> 级联属性 会调用 .getCar().setName(null); 如果car不存在为null,就会出错
- <beanid="parentBoss"abstract="true"
- class="com.baobaotao.attr.Boss">
- <propertyname="favorites">
- <set>
- <value>看报</value>
- <value>赛车</value>
- <value>高尔夫</value>
- </set>
- </property>
- </bean>
- <beanid="childBoss"parent="parentBoss">
- <propertyname="favorites">
- <setmerge="true">
- <value>爬山</value>
- <value>游泳</value>
- </set>
- </property>
- </bean>
为了简化操作可以使用p命名空间,p:属性名="xxx" p:属性名_ref="xxx",例如:
- <beanid="car"class="com.baobaotao.ditype.Car"
- p:brand="红旗&CA72"
- p:maxSpeed="200"
- p:price="20000.00"/>
- <beanid="boss"class="com.baobaotao.ditype.Boss"
- p:car-ref="car"/>
如果希望配置集合类型的bean,那么可以使用util命名空间
- <util:listid="favoriteList1"list-class="java.util.LinkedList">
- <value>看报</value>
- <value>赛车</value>
- <value>高尔夫</value>
- </util:list>
- <util:setid="favoriteSet1" >
- <value>看报</value>
- <value>赛车</value>
- <value>高尔夫</value>
- </util:set>
- <util:mapid="emails1">
- <entrykey="AM"value="会见客户"/>
- <entrykey="PM"value="公司内部会议"/>
- </util:map>
- <util:propertiesid="emailProps1"
- location="classpath:com/baobaotao/fb/mails.properties"/>
当然该util类还有其他用处,例如:
- <propertyname="brand">
- <util:constant
- static-field="com.baobaotao.fb.CarBrandType.HONG_QI"/>
- </property>
- <propertyname="brand">
- <util:property-pathpath="boss.car.brand"/> 找到id为boss的bean取出car中的brand属性
- </property>
构造方法注入:
按类型:
- <beanname="constructorBean"class="bean.ConstructorBean">
- <constructor-argtype="java.lang.String"value="1"/>
- <constructor-argtype="java.lang.Integer"value="2"/>
- </bean>
- <beanname="constructorBean"class="bean.ConstructorBean">
- <constructor-argindex="0"value="1"/>
- <constructor-argindex="1"value="2"/>
- </bean>
两者联合使用也可以:
- <beanname="constructorBean"class="bean.ConstructorBean">
- <constructor-argindex="0"type="java.lang.String"value="1"/>
- <constructor-argindex="1"type="int"value="2"/>
- </bean>
使用构造方法注入时有可能出现循环依赖,比如 Bean1中有Bean2属性,Bean2中也有Bean1属性,两者都使用构造注入就出现了循环依赖问题
工厂方法注入:(参考:http://550516671-qq-com.iteye.com/blog/803999)
非静态方法:
- public class CarFactory {
- public Car createHongQiCar(){
- Car car = new Car();
- car.setName("红旗");
- car.setSpeed("200");
- return car;
- }
- }
- <beanid="carFactory"class="com.lbx.factory.CarFactory"></bean>
- <bean id="car"factory-bean="carFactory"factory-method="createHongQiCar"></bean>
静态方法:
- public class CarFactory2 {
- public static Car createHongQiCar(){
- Car car = new Car();
- car.setName("红旗");
- car.setSpeed("200");
- return car;
- }
- }
- <beanid="car"class="com.lbx.factory.CarFactory2"factory-method="createHongQiCar"></bean>
Bean的作用域通过scope属性来指定,值如下:(参考:http://blog.csdn.net/mastermind/article/details/1932787)
singleton
getBean()
方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)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动态创建子类或实现类的方式实现的,例如
- <beanname="userManager" class="research.spring.beanfactory.ch2.UserManager">
- <lookup-methodname="getUserDao"bean="userDao"/>
- </bean>
这里如果调用userManager中的getUserDao会返回userDao,无论UserManager中getUserDao有无实现
方法替换:
一个bean中的方法用另一个bean中相同签名的方法替换掉,例如:
- <beanid="boss2"class="com.baobaotao.injectfun.Boss2"/>
- <bean id="boss1"class="com.baobaotao.injectfun.Boss1">
- <replaced-methodname="getCar"replacer="boss2"></replaced-method>
- t;/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
- spring IOC 详解
- spring的Ioc详解
- Spring IoC 使用详解
- Spring-- IOC容器详解
- Spring IOC 详解
- Spring IOC 详解
- spring IOC /DI 详解
- Spring--IOC容器详解
- Spring IoC 使用详解
- Spring ioc 详解
- Spring ioc 详解
- spring的Ioc详解
- Spring IoC 详解(上篇)
- Spring IoC 详解(下篇)
- Spring IoC AOP详解
- Spring IOC 详解
- 详解Spring IoC容器
- Spring — IoC详解
- linkbutton用法咯
- 容器初级入门
- 每日一Lua(3)-函数
- C#导出Excel后关闭进程(EXCEL.EXE)释放资源的解决方案
- WdatePicker日历控件使用方法
- Spring IOC 详解
- CyberLink for Java 编程指南
- Androi学习:Camera初探——控制摄像头拍照
- Qt 动画详解二
- jQuery基础学习(一)
- 查询按钮如何做到报表中
- windows phone开发学习--录音
- redis学习笔记之虚拟内存
- OpenCV c接口与c++接口