FactoryBean :是一个工厂Bean,可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。
BeanFactory :是Spring容器中的一个基类,也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,它对于Bean的创建有一个统一的流程。
FactoryBean
看看源码是怎么说的
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
//返回实例bean
@Nullable
T getObject() throws Exception;
//返回bean的类型
@Nullable
Class<?> getObjectType();
//是否是单例
default boolean isSingleton() {
return true;
}
}
自己写 FactoryBean 的实现
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
" >
<context:component-scan base-package="com.luo.dao"/>
</beans>
@Component("daoFactoryBean")//daoFactoryBean:得到是当前产生的对象,&daoFactoryBean:得到的是当前对象
public class DaoFactoryBean implements FactoryBean<TempFactoryBean> {
/*
* 实现了factoryBean接口
* spring中会存在两个bean
* 一个是当前对象(&+当前类的名字),
* 一个是getObject返回值 `
**/
public void test(){
System.out.println("DaoFactoryBean");
}
@Override
public boolean isSingleton() {
return true;
}
//返回的一个bean
@Override
public TempFactoryBean getObject() throws Exception {
//这里可以进行很多业务逻辑处理
return new TempFactoryBean();
}
@Override
public Class<?> getObjectType() {
return TempFactoryBean.class;
}
}
引入外部的资源
public class TempFactoryBean {
public void test(){
System.out.println("TempFactoryBean");
}
}
测试一下
public class Test02 {
public static void main(String[] args) throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spingmvc.xml");
DaoFactoryBean daoFactoryBean = (DaoFactoryBean) applicationContext.getBean("&daoFactoryBean");
TempFactoryBean tempFactoryBean = (TempFactoryBean) applicationContext.getBean("daoFactoryBean");
daoFactoryBean.test();
tempFactoryBean.test();
}
}
输出
"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:D:\IntelliJ IDEA\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar=52065:D:\IntelliJ IDEA\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program
DaoFactoryBean
TempFactoryBean
Process finished with exit code 0
根据结果可以知道,一个 实现了factoryBean接口的对象,会产生两个bean,一个是当前的对象,一个是当前对象生产的实例。要获取这个实例,就用当前对象的beanName获取,如果要获取当前对象,就用 &beanName 获取。
为什么要这么设计呢?
因为如果在xml中配置bean,此bean有很多属性或者说有第三方的依赖,就会配置大量的属性,大量的引用,太过于复杂。经典的例子有 MybatisSqlSessionFactoryBean
public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(MybatisSqlSessionFactoryBean.class);
private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();
private static final MetadataReaderFactory METADATA_READER_FACTORY = new CachingMetadataReaderFactory();
private Resource configLocation;
private MybatisConfiguration configuration;
private Resource[] mapperLocations;
private DataSource dataSource;
private TransactionFactory transactionFactory;
private Properties configurationProperties;
private SqlSessionFactory sqlSessionFactory;
private boolean failFast;
private Interceptor[] plugins;
private TypeHandler<?>[] typeHandlers;
private String typeHandlersPackage;
private Class<?>[] typeAliases;
private String typeAliasesPackage;
private Class<?> typeAliasesSuperType;
private LanguageDriver[] scriptingLanguageDrivers;
private Class<? extends LanguageDriver> defaultScriptingLanguageDriver;
private DatabaseIdProvider databaseIdProvider;
private Class<? extends VFS> vfs;
private Cache cache;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
private String typeEnumsPackage;
private GlobalConfig globalConfig;
public MybatisSqlSessionFactoryBean() {
}
public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
this.databaseIdProvider = databaseIdProvider;
}
public void setTypeAliasesPackage(String typeAliasesPackage) {
this.typeAliasesPackage = typeAliasesPackage;
}
public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType) {
this.typeAliasesSuperType = typeAliasesSuperType;
}
public void setTypeHandlersPackage(String typeHandlersPackage) {
this.typeHandlersPackage = typeHandlersPackage;
}
public void setTypeHandlers(TypeHandler... typeHandlers) {
this.typeHandlers = typeHandlers;
}
public void setTypeAliases(Class... typeAliases) {
this.typeAliases = typeAliases;
}
public void setConfigLocation(Resource configLocation) {
this.configLocation = configLocation;
}
public void setConfiguration(MybatisConfiguration configuration) {
this.configuration = configuration;
}
public MybatisConfiguration getConfiguration() {
return this.configuration;
}
public void setMapperLocations(Resource... mapperLocations) {
this.mapperLocations = mapperLocations;
}
public void setConfigurationProperties(Properties sqlSessionFactoryProperties) {
this.configurationProperties = sqlSessionFactoryProperties;
}
public void setDataSource(DataSource dataSource) {
if (dataSource instanceof TransactionAwareDataSourceProxy) {
this.dataSource = ((TransactionAwareDataSourceProxy)dataSource).getTargetDataSource();
} else {
this.dataSource = dataSource;
}
}
public void setTransactionFactory(TransactionFactory transactionFactory) {
this.transactionFactory = transactionFactory;
}
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
return this.sqlSessionFactory;
}
public Class<? extends SqlSessionFactory> getObjectType() {
return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
}
public boolean isSingleton() {
return true;
}
public void setTypeEnumsPackage(final String typeEnumsPackage) {
this.typeEnumsPackage = typeEnumsPackage;
}
public void setGlobalConfig(final GlobalConfig globalConfig) {
this.globalConfig = globalConfig;
}
}
.......
.......
.......
我们在使用 SqlSessionFactoryBean 的时候很简单,但是底层却进行了大量的处理。
以后如果遇到大量的配置或者说有依赖第三方,可以考虑使用这种方式