FactoryBean
一、只谈FactoryBean,不谈BeanFactory
众所周知,Spring容器管理着其内部的Bean,在这些Bean中可能存在着一类特殊的Bean,这一类特殊的Bean就是FactoryBean
。
FactoryBean与其它的Bean不一样的地方在于它能生产Bean
。
另外,从容器中获取它和它产生的Bean的方式有些特殊。
二、为什么使用FactoryBean?
一般情况下,Spring通过反射机制,利用< bean>中的class属性指定的实现类实例化Bean。
在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,需要在< bean>中提供大量的配置信息。配置方法的灵活性受限,这时采用编码方式可能会得到一个简单的方案。
Spring为此提供了一个org.springframework.beans.factory.FactoryBean
工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。可以隐藏实例化一些复杂Bean的细节。给上层应用带来便利。
从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean< T>的形式。
以Bean结尾,表示他是一个Bean,不同于其他bean的是:它实现了FactoryBean< T>的接口。该Bean的ID实际上是从BeanFactory中获取的实际的getObject()返回的对象,而不是FactoryBean本身。如果要获取FactoryBean对象,可以在id前面加一个&
符号来获取。
三、FactoryBean是什么?
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
/**
* 返回由FactoryBean创建bean的实例,如果是单例模式(isSingleton=true)则该实例会放在Spring容器单例的缓存池中。
*/
@Nullable
T getObject() throws Exception;
/**
* 返回FactoryBean创建的Bean实例
*/
@Nullable
Class<?> getObjectType();
/**
* 返回由FactoryBean创建的实例是不是单例
*/
default boolean isSingleton() {
return true;
}
}
四、FactoryBean怎么用?
在使用之前再次强调,我们为什么要用FactoryBean?
FactoryBean通常是用来创建比较复杂的Bean,一般的bean使用XML配置即可,但若是一个Bean的创建过程中涉及到很多其他Bean 和 复杂的逻辑,使用XML配置比较复杂的话,这时可以考虑使用FactoryBean
。
MyFactoryBean
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package com.jikang.config;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import java.util.Arrays;
import java.util.List;
/**
* @author yangjikang
* @date 2019/8/28 10:40
* @modified By yangjikang
* @since
*/
public class MyFactoryBean implements FactoryBean<List<String>>, InitializingBean, DisposableBean {
private String params = "";
private List<String> list;
@Override
public List<String> getObject() throws Exception {
return list;
}
@Override
public Class<?> getObjectType() {
return List.class;
}
@Override
public void destroy() throws Exception {
System.out.println("对象销毁...");
}
/**
* InitializingBean实现方法
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
//属性注入完后,调用该方法,该方法可以实现“业务”逻辑。创建出List<String>集合
String[] split = params.split(",");
list = Arrays.asList(split);
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
application.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myList" class="com.jikang.config.MyFactoryBean">
<property name="params" value="1,2,3,4"/>
</bean>
</beans>
App
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package com.jikang;
import com.jikang.config.MyFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
/**
* @author yangjikang
* @date 2019/8/26 17:09
* @modified By yangjikang
* @since
*/
public class App {
public static void main(String[] args) throws Exception{
// 用我们的配置文件来启动一个 ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
System.out.println("context 启动成功");
// 从 context 中取出我们的 MyFactoryBean
MyFactoryBean myFactoryBean = (MyFactoryBean) context.getBean("&myList");
System.out.println("通过&获取MyFactoryBean:"+myFactoryBean);
// 从 context 中取出我们的 ArrayList
List list = (List) context.getBean("myList");
System.out.println("MyFactoryBean实际返回的是:"+list);
//通过MyFactoryBean对象的getObject()方法获取对象
List<String> getListFormMyFactoryBean = myFactoryBean.getObject();
System.out.println("通过MyFactoryBean#getObject()获取的对象信息:"+getListFormMyFactoryBean);
//通过MyFactoryBean对象的getObjectType()方法获取类信息
Class getClassFormMyFactoryBean = myFactoryBean.getObjectType();
System.out.println("通过MyFactoryBean#getObjectType()获取的类信息:"+getClassFormMyFactoryBean);
//销毁
myFactoryBean.destroy();
}
}
控制台
推荐阅读
-
spring中FactoryBean中的getObject()方法实例解析
-
深入了解Spring中的FactoryBean
-
spring中FactoryBean中的getObject()方法实例解析
-
Spring 的 BeanFactory 和 FactoryBean 傻傻分不清?
-
Spring Framework 组件注册 之 FactoryBean
-
Spring5源码 - 08 BeanFactory和FactoryBean 源码解析 & 使用场景
-
Spring IOC高级特性(lazy-Init 延迟加载,FactoryBean,后置处理器)
-
关于实现了接口BeanPostProcessor 和 接口FactoryBean 的注意事项
-
BeanFactory与FactoryBean的理解
-
Spring中FactoryBean的作用和实现原理