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则添加了更多企业特定功能,例如:
- 与Spring的AOP功能集成。
- 消息资源处理。
- 活动发布。
- 应用层特定的上下文。
在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中有很大的用处。
网友评论