我所用的Spring版本是5.0.x的版本
BeanFactory和FactoryBean都是接口
1、BeanFactory
用于访问SpringBean容器的根接口。这是bean容器的基本客户机视图;
由BeanFactory中使用的对象实现的接口,这些对象本身就是单个对象的工厂,直接利用getbean()来获取对应的实例话bean的.
注意:其中BeanFactory的FACTORY_BEAN_PREFIX的属性是利用他来区分BeanFactory和FactoryBean的,如果你想获得这个bean的你需要在bean的名字前面加个"&",你才能获得对应的 FactoryBean的实现bean.
2、FactoryBean
a)如果一个bean实现了这个接口,它将被用作一个要公开的对象的工厂,而不是直接作为一个将要公开的bean实例。
注意:实现此接口的bean不能用作普通bean ,FactoryBean是以bean样式定义的,但是为bean引用公开的对象始终是getObject()创建的对象。
b) 当一个类当他的依赖关系很复杂的时候,而我们需要提供一个简单的依赖关系的时候,让外部更容易取配置的时候,可以使用FactoryBean.经典应用场景就是mybatis的SqlsessionFactoryBean对象
c)如果一个类实现了FactoryBean 那么spring容器当中存在两个对象,一个是getObject()返回的对象,另一个是当前对象 getObject得到的对象存在是当前类指定的名字,实现factoryBean对象是 "&" +当前类的名字
太抽象不多废话了直接上代码
例1如下:
TempDaoFactoryBean一个普通的bean
public class TempDaoFactoryBean {
public void test(){
System.out.println("TempDaoFactoryBean");
}
}
DaoFactoryBean是实现了FactoryBean接口
@Component("daoFactoryBean")
public class DaoFactoryBean implements FactoryBean {
public void testBean(){
System.out.println("testBean");
}
@Override
public Object getObject() throws Exception {
return new TempDaoFactoryBean();
}
@Override
public Class<?> getObjectType() {
return TempDaoFactoryBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
3、配置中信息
@Configuration
@ComponentScan("com.lquan")
public class Configration {
}
4、测试类
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext
= new AnnotationConfigApplicationContext(Configration.class);
// 注意获取factorybean的实例对象需要在对应beanname前面加"&"
DaoFactoryBean daoFactoryBean = (DaoFactoryBean) annotationConfigApplicationContext.getBean("&daoFactoryBean");
daoFactoryBean.testBean();
TempDaoFactoryBean tempDaoFactoryBean = (TempDaoFactoryBean) annotationConfigApplicationContext.getBean("daoFactoryBean");
tempDaoFactoryBean.test();
}
}
测试结果
注意:如果我们像不同类一样来获取factorybean的实例对象的话会报转换异常.
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext
= new AnnotationConfigApplicationContext(Configration.class);
// 注意获取factorybean的实例对象需要在对应beanname前面不加"&"
DaoFactoryBean daoFactoryBean = (DaoFactoryBean) annotationConfigApplicationContext.getBean("daoFactoryBean");
daoFactoryBean.testBean();
}
}
运行结果:
FactoryBean的应用
当一个类当他的依赖关系很复杂的时候,而我们需要提供一个简单的依赖关系的时候,让外部更容易取配置的时候,可以使用FactoryBean.经典应用场景就是mybatis的SqlsessionFactoryBean对象.
例二:
代码如下:
1、实现了FactoryBean接口的DaoFactoryBean
public class DaoFactoryBean implements FactoryBean {
private String info;
public void setInfo(String info) {
this.info = info;
}
public void testBean(){
System.out.println("testBean");
}
@Override
public Object getObject() throws Exception {
TempDaoFactoryBean tempDaoFactoryBean = new TempDaoFactoryBean();
// 统一处理
String[] infos = info.split(",");
tempDaoFactoryBean.setMsg1(infos[0]);
tempDaoFactoryBean.setDesc(infos[1]);
tempDaoFactoryBean.setAge(infos[2]);
return tempDaoFactoryBean;
}
@Override
public Class<?> getObjectType() {
return TempDaoFactoryBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
2、普通的类TempDaoFactoryBean
public class TempDaoFactoryBean {
private String msg1;
private String desc;
private String age;
public String getMsg1() {
System.out.println(msg1);
return msg1;
}
public void setMsg1(String msg1) {
this.msg1 = msg1;
}
public String getDesc() {
System.out.println(desc);
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getAge() {
System.out.println(age);
return age;
}
public void setAge(String age) {
this.age = age;
}
public void test(){
System.out.println("TempDaoFactoryBean");
}
}
3、配置
@Configuration
@ComponentScan("com.lquan.spring.xml")
@ImportResource("classpath:spring.xml")
public class Config {
}
4、spring.xml的配置
<?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.xsd">
<bean id="daoFactoryBean" class="com.lquan.spring.xml.dao.DaoFactoryBean">
<property name="info" value="你好,12,描述信息"/>
</bean>
</beans>
运行结果:
意义:简化了配置TempDaoFactoryBean在xml中的配置,不然的话就需要在spring配置对应相关的每一条属性like this
<?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.xsd">
<!-- <bean id="daoFactoryBean" class="com.lquan.spring.xml.dao.DaoFactoryBean">
<property name="info" value="你好,12,描述信息"/>
</bean>
-->
<bean id="tempDaoFactoryBean" class="com.lquan.spring.xml.dao.TempDaoFactoryBean">
<property name="desc" value="描述信息"/>
<property name="age" value="年龄"/>
<property name="msg1" value="信息压压"/>
</bean>
</beans>
相比之下利用factoryBean更有利于简化配置,
总结区别:
BeanFactory是个 Factory ,也就是 IOC 容器或对象工厂, FactoryBean 是个 Bean 。在 Spring 中,所有的 Bean 都是由 BeanFactory( 也就是 IOC 容器 ) 来进行管理的。但对 FactoryBean 而言,这个 Bean 不是简单的普通Bean ,而是一个能生产或者修饰对象生成的工厂 Bean, 它的实现与设计模式中的工厂模式和修饰器模式类似.