欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

# Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载

程序员文章站 2022-05-23 10:32:29
...

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。

@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的创建。

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

相关标签: 后端开发