# 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容器

ApplicationContextBeanFactory的子接口,也被称为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。

扫描二维码关注公众号,回复: 12931622 查看本文章
@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的创建。

。。。。。头都大了,好多都看不懂,有时间再看

猜你喜欢

转载自blog.csdn.net/qq_37248504/article/details/113704298