FactoryBean——Spring的扩展点之一

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;
}
发布了180 篇原创文章 · 获赞 49 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/P19777/article/details/104145092