容器中的工厂Bean:
此处的工厂Bean与前面介绍的实例工厂方法创建Bean、静态工厂创建Bean有所区别:
前面的那些工厂是标准的工厂模式,Spring只是负责调用工厂方法来创建Bean实例;
此处工厂Bean是Spring的一种特殊Bean,这种工厂Bean必须实现FactoryBean接口。
FactoryBean接口是工厂Bean标准的工厂Bean的接口,实现该接口的Bean只能当工厂Bean使用,当我们将工厂Bean部署在容器中,并通过getBean()方法来获取工厂Bean,容器不会返回FactoryBean实例而是FactoryBean的产品。
FactoryBean提供了三个方法:
<li>Object getObject();
<li>Class getObjectType();
<li>boolean isSingleton();
例如:
public class PersonFactory implements FactoryBean{
Person p = null;
public Object getObject() throws Exception{
if(p==null){
p = new Chinense();
return p;
}
}
public Class getObjectType(){
return Chinese.class;
}
public boolean isSingleton(){
return true;
}
}
<!--配置一个FactoryBean,和普通的Bean一样-->
<bean id="chinese" class=""/>
public static void main(String args[]){\
//以classpth下的bean.xml创建Reource对象
ClassPathResource re = new ClasspathResource("bean.xml");
//创建BeanFactory
XmlBeanFactory factory = new XmlBeanFactory(re);
Person p = (Person)factory.getBean("chinese");
//如需要获取FactoryBean本身则应该在bean id前加&
Person p = (Person)factory.getBean("&chinese");
}
对于初学者可能无法体会到工厂bean的作用,实际上,FactoryBean是Spring中非常有用的接口。例如:TransationProxyFactroyBean,这个工厂转为目标Bean创建事务代理.
6.深入理解依赖关系配置
<li>组件与组件之间的耦合,采用依赖注入管理,但是普通的javabean属性值,应直接在代码里设置。
<li>对于singleton作用域的bean,如果没有强制取消其预初始化行为,系统会在创建Spring容器时预初始化所有的singleton作用域的bean,与此同时,该bean依赖的bean也一起被实例化。
<li>BeanFactory与ApplicationContext实例化容器中的bean的时机不同,前者等到程序需要Bean实例才创建Bean,后者会预初始化容器中的所有Bean。
因为采用ApplicationContext作为Spring的容器,创建容器时,会创建容器中所有singleton作用域的所有bean,因此可能需要更多的系统资源,但是一旦创建成功。应用后面的 响应速度会很快,因此,对于普通的javaEE而言 ,建议使用ApplicationContext作为Spring的容器。
Bean实例4种属性值的设置:
①设置普通属性值value
略
②配置合作者Bean ref
可以为ref元素指定两个属性:bena、Local
bean:引用在不同一份XML配置文件中的其他Bean实例的ID属性值;
Local:引用同一份XML配置文件的其他Beanid属性值。
也可以不配置以上两个属性。
③组合属性名称:
public class A{
private Person p = new Person();
set/get....
}
`Spring配置文件`
<bean id="a" class="A">
<property name="p.name" value="aaa"/>
</bean>
④注入嵌套Bean:
>```
<bean id="" class="">
< property name="">
//属性为嵌套Bean 不能由Spring容器直接访问,因此没有id属性
<bean class="..."/>
</property>
</bean>
⑤注入集合值:
<list>
<value></value>
<value></value>
</list>
<map>
//每一个entry配置一个key-value对
<entry>
<key>
<value>.</value>
</key>
<value></value>
</entry>
</map>
<set>
<value></value>
<bean></bean>
<ref local=""/>
</set>
<props>
<prop key="">.....</prop>
<prop key="">.....</prop>
</props>
⑥注入方法返回值:
public class ValueGenrator{
public int getValue(){
return 6;
}
public static int getStaticValue(){
return 9;
}
}
<bean id="valueGenrator" class="lee.ValueGenrator"/>
<bean id="son1" class="Son">
<property name="age">
<bean class="org.springframework.bean.factory.congfig.MethodInvokignFactoryBean">
//配置非静态方法
<property name="targetObject" ref="valueGenrator"/>
//配置静态方法
<property name="targetMehtod" value="getStaticValue/>
</property>
</bean>
---
**强制初始化Bean**
>Spring有一个默认的规则,总是先初始化主调Bean,然后在初始化依赖Bean。
为了指定Bean在目标Bean之前初始化,可以使用**depends-on**属性.
>`大多数情况下`,Bean之间的依赖关系非常直接,Spring容器在返回Bean实例之前,完成Bean依赖关系的注入。假如Bean A依赖于Bean B,程序请求Bean A时,Spring容器会自动先初始化Bean B,再将Bean B注入Bean A,最后将具备完整依赖的Bean A返回给程序。
`在极端的情况下`,Bean之间的依赖不够直接。比如某个类的初始化块中使用其他Bean,Spring总是先初始化主调Bean,执行初始化块时还没有实例化主调Bean,被依赖的Bean还没实例化,此时将引发异常。
>为了让指定Bean在目标Bean之前初始化,可以使用 depends-on 属性,该属性可以在初始化主调Bean之前,强制初始化一个或多个Bean。
<bean id="beanOne" class="ExampleBean" depends-on="manager">
<property name="manager" ref="manager"/>
</bean>
<bean id="manager" class="ManagerBean"/>