FactoryBean就是生成Bean的, 其目的就是为了创建对象
FactoryBean 就是一个工厂Bean,相当于将工厂类放到了Spring中管理、当获取此Bean的时候返回的是此工厂生成的Bean。需要经过完整的一系列过程才可以创建出Bean
1.测试
public class Cat {
}
@Component
public class CatFactory implements FactoryBean<Cat> {
@Override
public Cat getObject() throws Exception {
return new Cat();
}
@Override
public Class<?> getObjectType() {
return Cat.class;
}
}
@Configuration
@ComponentScan("com.zzz.a8")
public class MainConfig {
@Bean
public CatFactory catFactory(){
return new CatFactory();
}
}
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Object bean = context.getBean("catFactory");
System.out.println(bean.getClass());
Object bean1 = context.getBean("&catFactory");
System.out.println(bean1.getClass());
}
}
当创建对象的过程复杂时可使用BeanFactory,调用方只需要注入就可使用
FactoryBean使创建对象操作 更加语义化
2.使用FactoryBean与 自己创建对象对比
既然factoryBean目的就是创建对象, 那如果我们自己写一个方法也可以完成同样的操作, 那为什么要使用factoryBean呢
使用方法创建对象
public class Cat {
}
@Component
public class CatFactory {
public Cat getCat(){
return new Cat();
}
}
public class Main {
@Autowired
private CatFactory catFactory;
public void main(String[] args) throws Exception{
Cat cat = catFactory.getCat();
}
}
总结:
- 对于调用方只需要知道对象即可, 不需要管生产方式, 符合迪米特法则, 知道的越少越好
- 通过FactoryBean创建对象与其他正常对象, 使用起来无差别
- 将操作复杂化, 全部封装到FactoryBean接口中, 使得类更具体化, 与Spring风格统一
- 但是, 单用这个类效果不大, 常常都是同时继承其他类, 实现其他接口协同
创建对象时需要依赖于 别的接口 监听数据,推送数据过来的接口 做一些数据处理时, 可以使用FactoryBean. 需要搭配其他接口协作, 依赖于Spring的某个生命周期内, 某个时间节点 来生成对象
3.FactoryBean 流程分析
DefaultListableBeanFactory.java
preInstantiateSingletons()
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
FactoryBeanRegistrySupport doGetObjectFromFactoryBean() AbstractBeanFactory getBean() -> doGetBean() -> getObjectForBeanInstance()
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
{
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
FactoryBeanRegistrySupport getObjectFromFactoryBean() -> doGetObjectFromFactoryBean()
调用 Bean工厂的 getObject() 方法生产指定Bean的实例对象
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
BeanFactory 接口调用其实现类的 getObject 方法来实现创建 Bean实例对象功能
4.总结
FactoryBean 的实现类有非常多,比如:Proxy、RMI、JNDI、ServletContextFactoryBean 等等。FactoryBean 接口为 Spring 容器提供了一个很好的封装机制,具体的 getObject()有不同的实现类根据不同的实现策略来具体提供。
- BeanFactory 是一个大工厂,是IOC容器的根基,有繁琐的 bean 生命周期处理过程,可以生成出各种各样的 Bean
- FactoryBean 是一个小工厂,它自己也是一个 Bean ,但是可以生成其他 Bean
|