美文网首页
Spring学习(三)-Bean的管理者BeanFactory

Spring学习(三)-Bean的管理者BeanFactory

作者: 一个菜鸟JAVA | 来源:发表于2021-02-03 16:40 被阅读0次

BeanFactory核心功能

在Spring中BeanDefinition用来描述一个Bean的内容,容器根据BeanDefinition的描述来创建Bean,同时容器还要提供查询Bean等一系列功能。我们把这个部分称作Bean的管理,而管理这些Bean的任务就交给了BeanFactory。所以BeanFactory的核心功能就是管理容器中的Bean。

BeanFactory相关子类即实现

BeanFactory只是一个工厂类接口,它提供的功能也比较有限。但是它的子类及实现类为它提供了更多丰富的功能。

HierarchicalBeanFactory

BeanFactory的子接口之一,它是父子级联IOC容器的接口,子容器可以通过接口方法访问到父容器。

public static void hierarchicalBeanFactory() {
    //创建父BeanFactory
    DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
    //创建并注册BeanDefinition到父BeanDefinition
    AbstractBeanDefinition userBd = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("id", 1)
            .addPropertyValue("userName", "tom")
            .getBeanDefinition();
    parent.registerBeanDefinition("user", userBd);
    //创建子BeanFactory
    HierarchicalBeanFactory child = new DefaultListableBeanFactory(parent);
    User user = (User) child.getBean("user");
    boolean containsLocalBean = child.containsLocalBean("user");
    boolean containsBean = parent.containsLocalBean("user");
    System.out.println("查找到的Bean信息:" + user);
    System.out.println("child本地是否存在:" + containsLocalBean);
    System.out.println("parent本地是否存在:" + containsBean);
}

上面代码的返回结果如下:

查找到的Bean信息:User{id=1, userName='tom'}
child本地是否存在:false
parent本地是否存在:true

HierarchicalBeanFactory在获取Bean时会先从本地查找,如果本地找不到再从父BeanFactory中查找,如果循环直到找到对应的Bean或者BeanFactory没有父级了。

ListableBeanFactory

BeanFactory接口只提供了获取单个Bean的方法,而ListableBeanFactory则提供了集合相关操作,便于我们一次获取多个Bean。

public static void listableBeanFactory(){
    //创建ListableBeanFactory
    ListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //定义user1的BeanDefinition
    AbstractBeanDefinition user1Bd = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("id", 1)
            .addPropertyValue("userName", "tom")
            .getBeanDefinition();
    //定义user2的BeanDefinition
    AbstractBeanDefinition user2Bd = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("id", 2)
            .addPropertyValue("userName", "jack")
            .getBeanDefinition();
    //注册
    ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("user1",user1Bd);
    ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("user2",user2Bd);
    //从容器中类型为User的Bean实例
    Map<String, User> users = beanFactory.getBeansOfType(User.class);
    users.forEach((k,v) -> System.out.printf("%s = %s\r\n",k,v));
}

上面的代码运行结果如下:

user1 = User{id=1, userName='tom'}
user2 = User{id=2, userName='jack'}

上面的代码,我们通过ListableBeanFactory的getBeansOfType获取所有类型为User的Bean实例。

AutowireCapableBeanFactory

定义了将容器中的Bean按照某种规则进行自动装配的方法,例如:按名称匹配、按类型匹配等。同时它还支持将容器内的Bean注入到不受容器管理的外部实例。具体请参照下面的代码示例:

User类

public class User{
    private Integer id;
    private String userName;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                '}';
    }
}

UserHolder类

public class UserHolder{
    private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "UserHolder{" +
                "user=" + user +
                '}';
    }
}

示例代码:

public static void autowireCapableBeanFactory(){
    //创建BeanFactory
    AutowireCapableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //创建UserBeanDefinition
    AbstractBeanDefinition userBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
            .addPropertyValue("id", 1)
            .addPropertyValue("userName", "tom")
            .getBeanDefinition();
    //创建UserHolderBeanDefinition
    AbstractBeanDefinition userHolderBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class)
            .setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE)
            .getBeanDefinition();
    //注册UserBeanDefinition和UserHolderBeanDefinition
    ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("user",userBeanDefinition);
    ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("userHolder",userHolderBeanDefinition);
    //按照类型自动将User装配到UserHolder中
    UserHolder userHolder = beanFactory.getBean(UserHolder.class);
    User user = beanFactory.getBean(User.class);
    System.out.println(user);
    System.out.println(userHolder);
    System.out.println(userHolder.getUser() == user);
    //不受Spring容器管理的myUserHolder,同样也可以将容器中的UserBean注入到容器外部对象
    UserHolder myUserHolder = new UserHolder();
    beanFactory.autowireBeanProperties(myUserHolder,AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE,false);
    System.out.println(myUserHolder.getUser() == user);
}

最后运行结果如下:

User{id=1, userName='tom'}
UserHolder{user=User{id=1, userName='tom'}}
true
true

从运行结果可以看出:上面的结果真好体现了AutowireiCapableBeanFacotry可以按照规则自动装配(本例子中我们设置为按照类型自动装配),同时我们自己手动New出的myUserHolder是一个容器外部实例,我们使用AutowireiCapableBeanFacotry将容器内部实例user注入到外部的实例中。

ConfigurableBeanFactory

ConfigurableBeanFactory定义了许多BeanFactory的配置相关方法,主要包含了父容器、类加载、元数据缓存开关、处理和加载Bean细节方法、处理Bean后处理器、注册范围等等一系列配置项。

ConfigurableListableBeanFactory

它是一个组合接口,它继承了ListableBeanFactory, AutowireCapableBeanFactory,,ConfigurableBeanFactory三个接口,同时提供忽律自动配置的方法、注册可分解依赖的方法、判断指定Bean是否有资格作为自动装配候选资格的方法、根据bean名称返回BeanDefinition的方法、冻结所有Bean配置相关方法、使所有非延迟加载的单例类都实例化方法。

DefaultListableBeanFactory

前面都是各种接口,这些接口基本上都是直接或者间接继承了BeanFactory,同时不同的接口都有着自己特色的功能,最后组合称成ConfigurableListableBeanFactory接口。而该接口最后的主要实现就是DefaultListableFactory。

DefaultListableBeanFactory.png

为了便于理解,这里面删除了部分内容,只留下了BeanFactory相关的接口及实现。在之前的示例代码中,我们一直都是使用DefaultListableFactory这个BeanFactory的实现来做演示,因为它综合了之前接口的所有功能,所以这个类非常重要。

BeanFactory与ApplicationContext

在Spring的官方文档中描述中,BeanFactory提供了一种高级配置机制,能够管理任何类型的对象。而ApplicationContext是BeanFactory的子接口,简单的说就是BeanFactory提供了配置框架和基本功能,而ApplicationContext则添加了更多企业特定功能,例如:

  1. 与Spring的AOP功能集成。
  2. 消息资源处理。
  3. 活动发布。
  4. 应用层特定的上下文。

在Spring官方文档关于BeanFactory or ApplicationContext中官方更推荐使用ApplicationContext的实现,因为BeanFactory所有的功能在ApplicationContext中几乎都能使用。他们的对比如下表所示:

Feature BeanFactory ApplicationContext
Bean instantiation/wiring Yes Yes
Integrated lifecycle management No Yes
AutomaticBeanPostProcessorregistration No Yes
AutomaticBeanFactoryPostProcessorregistration No Yes
ConvenientMessageSourceaccess (for internalization) No Yes
Built-inApplicationEventpublication mechanism No Yes

总结

BeanFactory的是IOC容器的基础,而更重的点在于它提供了对Bean的管理上面,这也是Spring的核心之一。明白这一点,在使用和学习Spring中有很大的用处。

相关文章

网友评论

      本文标题:Spring学习(三)-Bean的管理者BeanFactory

      本文链接:https://www.haomeiwen.com/subject/jrkmtltx.html