FactoryBean和BeanFactory虽然名字很像,但是这两者是完全不同的两个概念,用途上也是天差地别。BeanFactory是一个Bean工厂,我们可以简单理解为它就是我们平常所说的Spring容器,它完成了Bean的创建、自动装配等过程,存储了创建完成的单例Bean。而FactoryBean通过名字看,我们可以猜出它是Bean,但它是一个特殊的Bean,一个工厂Bean,用来生成其他Bean
使用FactoryBean
FactoryBean的特殊之处在于它本身并不像其他bean一样可以直接使用,FactoryBean.getObject()方法返回值所代表的Bean才是我们真正要使用的bean。
先通过如下示例代码来感受下FactoryBean。
/**
* Spring配置类,让其扫描到我们的FactoryBean
*/
@Configuration
@ComponentScan("com.c")
public class AppConfig {
}
/**
* 自定义的FactoryBean
*/
@Component
public class CustomerFactoryBean implements FactoryBean<UserService> {
@Override
public UserService getObject() throws Exception {
return new UserService();
}
@Override
public Class<?> getObjectType() {
return UserService.class;
}
}
/**
* FactoryBean创建的类,注意没有@Component注解
* 也就是说,该类没有向spring容器中注册
*/
public class UserService {
}
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
// 打印Spring容器中所有的bean的定义
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
System.out.println(" ");
System.out.println(" ");
// 获取UserService的实例
System.out.println(applicationContext.getBean(UserService.class));
// 这种方式获取userService会报错
// System.out.println(applicationContext.getBean("userService"));
// 获取我们自定义的FactoryBean
System.out.println(applicationContext.getBean("customerFactoryBean")); System.out.println(applicationContext.getBean(UserService.class) == applicationContext.getBean("customerFactoryBean"));
// 获取CustomFactoryBean类本身的实例
System.out.println( applicationContext.getBean("&customerFactoryBean"));
}
}
输出
// 上面这些是spring内部的bean,不用管
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
// 可以看到我们写的两个类,并没有UserService
appConfig
customerFactoryBean
// 正确的获取到了实例
c.UserService@12d3a4e9
// 获取CustomFactoryBean获取出来的也是UserService
c.UserService@12d3a4e9
true
// 这样才获取出了真正的FactoryBean
c.CustomerFactoryBean@240237d2
FactoryBean的好处
FactoryBean的好处在于,我们可以非常灵活的定义自己的bean,而不被spring的容器所限制。
比如说,我们现在想要有一种bean,这个bean是动态生成的一个接口的实例,这种你要怎么办?这种你没办法向容器中注册。当然办法其实也是有的,只是不够优雅,FactoryBean就是一种优雅的注册方式。
我们可以CustomFactoryBean类中写出生成接口实例的生成逻辑,然后将这个CustomFactoryBean注册到容器中就行了
FactoryBean在Mybatis整合Spring中的使用
Mybatis整合Spring中的MapperFactoryBean类,就是一个FactoryBean的实现,有了他我们就能在Spring中获取到dao接口的实例了,当然他是向SqlSessionFactory获取实例
核心方法
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
/**
* {@inheritDoc}
*/
@Override
public Class<T> getObjectType() {
return this.mapperInterface;
}