# Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载
Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载
Spring IOC概念
简单来说就是创建实例的操作由Spring完成,使用的时候直接拿来用就行了。举个例子一般实例化一个对象会进行new操作,而Spring中new操作有Spring完成。
BeanFactory容器
在 Spring 中,BeanFactory
是 IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。。BeanFactory是基础类型的IOC容器。它在org.springframework.beans.factory.BeanFactory接口定义,提供Bean的注册。BeanFactory接口的使用有ApplicationContext继承类和BeanFactory实现类。
BeanFactory接口源码
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
BeanFactory主要实现类
-
StaticListableBeanFactory
:StaticListableBeanFactory实现ListableBeanFactory,ListableBeanFactory继承BeanFactory接口。StaticListableBeanFactory
不包括bean的实例化过程。需要手动add操作注册bean。 -
DefaultListableBeanFactory
:BeanFactory的默认实现。
@Test
public void test1(){
// 定义Bean的文件地址
ClassPathResource resource=new ClassPathResource("HelloWorld.xml");
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
HelloWorld helloWorld = factory.getBean(HelloWorld.class);
System.out.println(helloWorld.toString());
}
-
XmlBeanFactory
:从xml中配置元数据。
@Test
public void test7(){
Resource resource = new ClassPathResource("HelloWorld.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
HelloWorld helloWorld = beanFactory.getBean(HelloWorld.class);
System.out.println(helloWorld.toString());
}
FactoryBean接口
Spring 中为提供了两种类型的 bean,一种就是普通的 bean,我们通过 getBean(id)
方法获得是该 bean 的实际类型,另外还有一种 bean 是 FactoryBean
,这个bean可以生产别的bean,我们通过 getBean(id)
获得是该工厂所产生的 Bean 的实例,而不是该 FactoryBean
的实例。实现Factory接口的类可以改变bean。
FactoryBean实现demo
HelloWorldFactoryBean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloFactoryBean" class="com.li.test.factorybean.HelloFactoryBean" >
<property name="message" value="张三" ></property>
<property name="id" value="1"></property>
</bean>
</beans>
HelloFactoryBean
// 实现FactoryBean接口重写三个方法
public class HelloFactoryBean implements FactoryBean<HelloWorld> {
private int id;
private String message;
@Override
public HelloWorld getObject() throws Exception {
// 在这里可以对生成的Bean实例进行操作
return new HelloWorld(id,"李四");
}
@Override
public Class<?> getObjectType() {
// 定义生成bean的类型
return HelloWorld.class;
}
/**
* 工厂所管理的对象是否为单例的
* 即如果该方法返回true,那么通过getObject()方法返回的对象都是同一个对象
*/
@Override
public boolean isSingleton() {
return true;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Test
@Test
public void test1(){
BeanFactory beanFactory = new ClassPathXmlApplicationContext("HelloWorldFactoryBean.xml");
HelloWorld helloWorld = (HelloWorld) beanFactory.getBean("helloFactoryBean");
System.out.println(helloWorld.toString());
}
// 输出:HelloWorld{id=1, message='李四'} 发现message变化了。
ApplicationContext容器
ApplicationContext是BeanFactory的子接口,也被称为Spring上下文。Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。
ApplicationContext常用实现类
-
ClassPathXmlApplicationContext
:从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作。
@Test
public void test3(){
AbstractApplicationContext context=new ClassPathXmlApplicationContext("HelloWorld.xml");
HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
System.out.println(helloWorld);
context.registerShutdownHook();
}
-
FileSystemXmlApplicationContext
:类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作。
Spring Bean工厂准备(Bean被定义)
Spring入口
@Test
public void test4(){
ApplicationContext context=new ClassPathXmlApplicationContext("AopXmlBeans.xml");
Message message = (Message) context.getBean("message");
message.getId();
message.getMessage();
message.showMessage();
}
new ClassPathXmlApplication()之后发生了什么?
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 初始化容器中bean的配置信息
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
重点方法refresh()
- 看看这个refresh()方法是什么?这个方法在抽象
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext
类中。这个方法至关重要:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 为刷新做好准备
prepareRefresh();
// 告诉子类刷新内部bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备在此上下文中使用的bean工厂。
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
// 调用作为上下文中的bean注册的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的bean处理器。
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的消息源。
initMessageSource();
// 为此上下文初始化事件多播程序。
initApplicationEventMulticaster();
// 在特定的上下文子类中初始化其他特殊bean。
onRefresh();
// 检查侦听器bean并注册它们。
registerListeners();
// 实例化所有剩余的(非lazy-init)单例。
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件。
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例,以避免悬浮资源。
destroyBeans();
// 重置“活跃”的旗帜。
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// 在Spring的核心中重置公共自省缓存
resetCommonCaches();
}
}
}
-
prepareRefresh()
:容器刷新前的准备、设置上下文状态、获取属性等。 -
onfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
:获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition
等。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新上下文环境、销毁原有创建新的beanFactory
refreshBeanFactory();
return getBeanFactory();
}
refreshBeanFactory():如果beanfactory存在,则销毁然后再创建新的beanfactory。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
// 销毁bean
destroyBeans();
closeBeanFactory();
}
try {
// 创建新的beanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
**loadBeanDefinitions()**方法为每个bean生成beanDefinition。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 为给定的BeanFactory创建一个新的XmlBeanDefinitionReader。
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 使用此上下文配置bean定义阅读器
// 资源加载环境。
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//允许一个子类提供自定义的读取器初始化,
//然后继续实际加载bean定义。
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
-
prepareBeanFactory(beanFactory)
:配置标准的beanFactory,设置ClassLoader,设置SpEL表达式解析器,添加忽略注入的接口,添加bean,添加bean后置处理器等。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 告诉内部bean工厂使用上下文的类装入器等。
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 使用上下文回调配置bean工厂。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory接口没有注册为普通工厂中的可解析类型。
// MessageSource作为一个bean注册(并找到自动装配)。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//将早期后处理器注册为applicationlistener来检测内部bean。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认的环境bean。
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
-
postProcessBeanFactory(beanFactory)
:所有的beanDefinition已经加载,但是还没有实例化。允许在子类中对beanFactory进行扩展处理。比如添加ware相关接口自动装配设置,添加后置处理器等,是子类扩展prepareBeanFactory(beanFactory)的方法。在应用上下文的内部bean factory初始化之后修改bean factory。所有的bean definitions已经被加载,但是还没有bean被实例化。在明确的ApplicationContext实现中允许指定BeanPostProcessors等的注册
// 注册request/session scopes等
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// ServletContextAwareProcessor中拿到应用上下文持有的servletContext引用和servletConfig引用
// 添加ServletContextAwareProcessor处理器
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
// 在自动注入时忽略指定的依赖接口
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
// 注册web应用的scopes
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 注册和环境有关的beans
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
-
invokeBeanFactoryPostProcessors(beanFactory)
:实例化并调用所有注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor
的bean,在beanFactory标准初始化之后执行)。执行了BeanDefinitionRegistryPostProcessor(此处只有ConfigurationClassPostProcessor)
执行了BeanFactoryPostProcessor
完成了@Configuration配置文件的解析,并且把扫描到的、配置的Bean定义信息都加载进容器里
BeanPostProcessor
使用例子:实现BeanPostProcessor重写postProcessBeforeInitialization()在这个方法中可以对当前的Bean进行修改。最后拿到的bean是修改之后的Bean。
@Configuration
public class UserBean {
private static final Logger logger = Logger.getLogger(String.valueOf(UserBean.class));
@Bean(name = "myUser")
public User getUser(){
User user = new User();
user.setAge(23);
Date date = new Date();
user.setDate(date);
user.setName("张三");
logger.info("=====> UserBean配置信息:"+ JSONObject.toJSONString(user));
return user;
}
}
@Component
public class UserBeanPostProcessor implements BeanPostProcessor {
private static final Logger logger = Logger.getLogger(String.valueOf(UserBeanPostProcessor.class));
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
final String name = "myUser";
if(name.equals(beanName)){
User user = (User) bean;
user.setName("李四");
user.setDate(new Date());
logger.info("=====> postProcessBeforeInitialization():"+ JSONObject.toJSONString(user));
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
-
registerBeanPostProcessors(beanFactory)
:实例化和注册beanFactory中扩展了BeanPostProcessor
的bean。将 BeanPostProcessor 注册到 BeanFactory 中,并没有执行
// 获取容器中类型为BeanPostProcessor的bean的名城
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
BeanPostProcessor
实现类有:Spring默认的三个AutowiredAnnotationBeanPostProcessor
(处理被@Autowired
注解修饰的bean并注入)RequiredAnnotationBeanPostProcessor
(处理被@Required
注解修饰的方法)CommonAnnotationBeanPostProcessor
(处理@PreDestroy
、@PostConstruct
、@Resource
等多个注解的作用)等。
-
initMessageSource()
:初始化国际化工具类MessageSource -
initApplicationEventMulticaster()
:初始化事件广播器 -
onRefresh()
:模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情。 -
registerListeners()
:注册监听器,广播early application events -
finishBeanFactoryInitialization(beanFactory)
:实例化所有剩余的(非懒加载)单例
比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。实例化的过程各种BeanPostProcessor开始起作用。 -
finishRefresh()
:refresh做完之后需要做的其他事情。清除上下文资源缓存(如扫描中的ASM元数据) 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle
接口的bean并执行start()方法)。发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作。
SpringBean 创建
refresh()的finishBeanFactoryInitialization()开始
循环所有定义的bean,判断是不是工厂bean,如果是普通的bean,直接调用getBean(),getBean()中调用doGetBean()。doGetBean方法中获得Bean并且返回。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
//遍历副本以允许init方法注册新的bean定义。
//虽然这可能不是常规工厂引导的一部分,但它在其他方面工作得很好。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非惰性单例bean的初始化…
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) {
final 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);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
Object singletonInstance = getSingleton(beanName);
从单例缓存池中获取。getBean()方法特别长,本质是获取一个javaBean,内部实现了Bean的创建。
。。。。。头都大了,好多都看不懂,有时间再看
推荐阅读
-
Spring源码剖析2:Spring IOC容器的加载过程
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
Spring源码分析-IOC容器BeanFactory的应用场景
-
Spring框架源码分析(IoC):BeanFactory和ApplicationContext容器家族
-
Spring—IOC容器中Bean的生命周期方法
-
Spring中BeanFactory和ApplicationContext的作用和区别(推荐)
-
Spring IOC DI依赖注入 IOC容器 Spring Bean的声明周期
-
Spring概述 IOC容器和bean的配置
-
Spring源码剖析2:Spring IOC容器的加载过程
-
spring通用获取ioc容器中配置的bean的工具类