问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Spring框架FactoryBean接口的作用和应用

创作时间:
作者:
@小白创作中心

Spring框架FactoryBean接口的作用和应用

引用
CSDN
1.
https://blog.csdn.net/weixin_53391173/article/details/139922339

FactoryBean源码解读

FactoryBean 是 Spring 框架 beans.factory包中的一个接口,从字面意思可以理解为工厂bean,它是干什么的,类名上的泛型又是指什么,有什么作用?

注释看不懂没关系,先看一下它有哪些方法。

public interface FactoryBean<T> {
    // 获取实例
    @Nullable
    T getObject() throws Exception;
    // 获取实例的class类型
    @Nullable
    Class<?> getObjectType();
    // 实例默认为单例
    default boolean isSingleton() {
        return true;
    }
}

方法看完了,还是不知道它能干嘛,继续看它的子类。

子类真多,一个屏幕放不下,找几个看看。

FactoryBean的子类

先看两个简单的实现类:

1. AuthenticationManagerFactoryBean类

AuthenticationManagerFactoryBean是spring-boot-starter-security 框架中的一个类,这个类实现了FactoryBean, BeanFactoryAware 两个接口的功能。

BeanFactoryAware 接口在《Spring框架Aware接口的作用和应用》一文中已经介绍过,它是用于在当前类初始化时获取 BeanFactory 接口以供当前类使用的。

FactoryBean的泛型位置放置了一个类AuthenticationManager。

AuthenticationManagerFactoryBean实现了FactoryBean接口中3个方法

在getObject() 方法中创建了AuthenticationManager实例并返回。

在该方法的最后一行代码可以看出,AuthenticationManager的实例是交给ProviderManager 对象管理的。

因此,在getObjectType()方法中返回的是ProviderManager对象的class。

在 isSingleton()方法中返回的依旧是单例模式。

从以上代码的分析,我们可以得出一个结论,AuthenticationManagerFactoryBean类是用来创建AuthenticationManager对象实例的工厂bean类。

2. CronTriggerFactoryBean类

CronTriggerFactoryBean是Spring框架定时任务 org.springframework.scheduling.quartz 包中的一个类,这个类实现了FactoryBean, BeanNameAware, InitializingBean 3个接口的功能。

BeanNameAware 是用于在当前类初始化时获取当前类的bean名称的。

InitializingBean 接口是用于重写初始化方法的。

FactoryBean的泛型位置放置了一个类CronTrigger。

CronTrigger是定时任务的表达式对象。

在重写的 afterPropertiesSet() 初始化方法中,new 了一个 CronTriggerImpl对象并返回。

CronTriggerImpl位于定时任务框架 org.quartz中,它是CronTrigger的实现类。

接下来就是FactoryBean三个方法的实现:

getObject() 方法中直接初始化方法中创建的cronTrigger变量。

getObjectType()方法返回的是CronTrigger的class,它是CronTriggerImpl的超类。

isSingleton()方法中返回的是单例模式。

从以上代码的分析,我们也可以得出一个结论,CronTriggerFactoryBean类是用来创建CronTriggerFactory对象实例的工厂bean类。

再来看两个复杂一些的抽象类。

3. AbstractFactoryBean抽象类

AbstractFactoryBean实现了FactoryBean, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean 5个接口。

FactoryBean泛型位置的参数还是泛型。

BeanClassLoaderAware接口是用于在当前类初始化时获取类加载对象ClassLoader的。

BeanFactoryAware接口是用于在当前类初始化时获取BeanFactory的。

InitializingBean 接口是用于重写初始化方法的。

DisposableBean 接口是用于重写销毁方法的。

在初始化方法中,如果是单例则进行实例化:

protected abstract T createInstance() throws Exception;
@Override
@Nullable
public abstract Class<?> getObjectType();
@Override
public final T getObject() throws Exception {
    if (isSingleton()) {
        return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
    }
    else {
        return createInstance();
    }
}

实例化是个抽象方法,由其子类实现具体实例化逻辑。

getObjectType()也是抽象方法,由其子类实现。

getObject()是个final方法,子类不能更改,如果是单例则返回单例实例,否则每次调用返回一个新的实例。

在AbstractFactoryBean抽象类中,我们最关心的FactoryBean中的2个方法,一个由其子类实现,一个由抽象类实现。不管是子类还是抽象类,目的都是一样的。

4. ListFactoryBean类

ListFactoryBean是AbstractFactoryBean<List>的子类,通过这个头可以看出它是创建一个List集合的。

在getObjectType()方法中,直接返回List集合的class。

在createInstance()方法中,实现了List集合的实例化逻辑。

还有很多抽象类、实现类,我们就不举例了。

从以上3个类我们可以推断出,FactoryBean就是一个创建和管理bean实例的特殊工厂bean。

FactoryBean的子类很多,但是子接口只有一个,我们也看下。

SmartFactoryBean子接口和应用

1. SmartFactoryBean源码解读

SmartFactoryBean接口扩展了FactoryBean接口

public interface SmartFactoryBean<T> extends FactoryBean<T> {
    // 是否为原型,默认false
    default boolean isPrototype() {
        return false;
    }
    // 是否提前初始化,默认false
    default boolean isEagerInit() {
        return false;
    }
}

这个接口增加了两个方法:

isPrototype()方法,判断当前要创建的bean实例是否是原型。

isEagerInit()方法,判断当前要创建的bean实例是否提前实例化。

2. FactoryBean和SmartFactoryBean的应用比较

1)定义一个bean

public class MyBean2{
    
    public MyBean2() {
        System.out.println("1、实例化 MyBean2");
    }
   
    public void fun(){
        System.out.println("2、调用  MyBean2 的 fun 方法");
    }
}

2)把MyBean2对象封装到MyBean2FactoryBean中

@Component
public class MyBean2FactoryBean implements SmartFactoryBean<MyBean2>{
    
    private MyBean2 myBean2;
    
    @Override
    public MyBean2 getObject() throws Exception {
        if(myBean2 == null){
            myBean2 = new MyBean2();
        }
        return myBean2;
    }
    @Override
    public Class<?> getObjectType() {
        return MyBean2.class;
    }
    
    @Override
    public boolean isEagerInit() {
        return true;
    }
}

测试FactoryBean接口时,可以把SmartFactoryBean替换成FactoryBean,并把isEagerInit注释掉。

3)测试代码

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
/**
 * SmartFactoryBean接口演示代码,是否提前实例化的验证
 * @author 
 * @Description
 *
 */
public class SpringApp5 {
    
    public static void main(String[] args) {   
        
       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBean2FactoryBean.class);
      
       MyBean2FactoryBean myBean2FactoryBean = context.getBean(MyBean2FactoryBean.class);
       try {
           System.out.println("还没有调用呢");
            MyBean2 myBean = myBean2FactoryBean.getObject();
            myBean.fun();
       } catch (Exception e) {
            e.printStackTrace();
       }
       context.close();
   }
}

当我们使用 FactoryBean 的时候,Spring 在实例化 Bean 的时候,实例化的是MyBean2FactoryBean 工厂 Bean,MyBean2则是在工厂 Bean中实例化的。

当把工厂bean更改为FactoryBean的时候,运行结果如下:

Creating shared instance of singleton bean 'myBean2FactoryBean'
还没有调用呢
1、实例化 MyBean2
4、调用 MyBean2 的 fun 方法

当把工厂bean更改为SmartFactoryBean的时候,并设置提前实例化时,运行结果如下:

Creating shared instance of singleton bean 'myBean2FactoryBean'
1、实例化 MyBean2
还没有调用呢
4、调用  MyBean2 的 fun 方法

当我们把 isEagerInit() 返回 true时,实例化提前了,没有使用就被实例化了。

最后总结

FactoryBean是一个特殊的bean,用于创建和管理自定义 Bean 实例的工厂bean,其中类名中的泛型就是要创建Bean的类名,如果子类是一个抽象类,那么具体的创建实例过程会延伸到其子类。

FactoryBean定义了一种创建 Bean 的方式,允许在 Bean 的创建过程中进行更多的自定义操作。通过实现 FactoryBean 接口,我们可以创建复杂的 Bean 实例,或者在 Bean 实例化之前进行一些额外的逻辑处理,比如重写初始化方法的InitializingBean等等。

在看源码时,如果看到某个类名是:XxxxFactoryBean,我们就能在瞬间知道这个类是创建Xxxx实例的工厂bean。如果还带有泛型XxxxFactoryBean,就说明这是一个抽象类,具体的创建实例的过程在其子类中。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号