Spring(03)Spring IOC 概述

Spring(03)Spring IOC 概述

Spring 核心编程思想目录:https://www.cnblogs.com/binarylei/p/12290153.html

1. Spring IoC 依赖查找

1.1 根据 Bean 名称查找

  • 实时查找

    User user = (User) beanFactory.getBean("user");
    
  • 延迟查找

    bean 配置如下:

    <bean id="user1" class="com.binarylei.spring.ioc.bean.User" lazy-init="true"/>
    <bean id="user2" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user1"/>
    </bean>
    

    通过 ObjectFactory 获取 bean 时会延迟加载 bean,只有手动调用 getObject 方法都会初始化 User 对象。将 User 设置为 lazy-init="true" 效果会更明显,Spring 会默认初始化所有非懒加载的 bean。

    ObjectFactory<User> objectFactory = (ObjectFactory) beanFactory.getBean("user2");
    User user = objectFactory.getObject();
    

思考: ObjectFactory 和 FactoryBean 都是通过 getObject 创建对象,它们有什么区别呢?

  1. ObjectFactory :是属于懒加载 bean,只有手动调用 getObject 都会初始化 bean。

  2. FactoryBean:当加载 FactoryBean 的同时就会调用 getObject 初始化对象,不属于懒加载 bean。Spring 中如果想要获取 FactoryBean 本身,可以在 bean 名称前加载 & 符号。

    FactoryBean<User> factoryBean = (FactoryBean<User>) beanFactory.getBean("&user");

1.2 根据 Bean 类型查找

  • 单个 Bean 对象

    User user = beanFactory.getBean(User.class);
    
  • 集合 Bean 对象

    Map<String, User> userMap = ((DefaultListableBeanFactory) beanFactory)
        .getBeansOfType(User.class);
    

思考: beanFactory.getBean(User.class),如果返回多个对象,Spring 会如何处理,如何解决?

当 Spring 容器中有多个 User 对象时,Spring 会抛出异常 NoUniqueBeanDefinitionException,这时可以通过标注 primary 来处理。

<bean id="user1" class="com.binarylei.spring.ioc.bean.User" primary="true"/>

1.3 根据 Bean 名称 + 类型查找

User user = beanFactory.getBean("user", User.class);

1.4 根据 Java 注解查找

Map<String, Object> beanMap = ((DefaultListableBeanFactory) beanFactory)
    .getBeansWithAnnotation(Component.class);

2. Spring IoC 依赖注入

有 UserManager 类,如何将 users 注入呢?

@Data
public class UserManager {
    private BeanFactory beanFactory;
    private SuperUser superUser;
    private List<User> users;
} 

2.1 根据 Bean 名称注入

  • 单个Bean 对象

    <bean id="userManager" class="com.binarylei.spring.ioc.bean.UserManager">
        <property name="superUser" ref="user"/>
    </bean>
    
  • 集合 Bean 对象

    <bean id="userManager" class="com.binarylei.spring.ioc.bean.UserManager">
        <property name="users">
            <util:list>
                <ref bean="user1"/>
                <ref bean="user2"/>
            </util:list>
        </property>
    </bean>
    

2.2 根据 Bean 类型注入

<bean id="userManager" class="com.binarylei.spring.ioc.bean.UserManager" 
      autowire="byType"/>

2.3 注入容器內建 Bean 对象

如 Environment 对象。

2.4 注入非 Bean 对象

如 BeanFacory 可以正常注入到 UserManager 中。如果通过 beanFactory.getBean(BeanFactory.class) 会抛出 NoSuchBeanDefinitionException 异常。

2.5 注入类型

  • 实时注入
  • 延迟注入

2.6 注入模式

  • 手动模式- 配置或者编程的方式,提前安排注入规则
    • XML 资源配置元信息
    • Java 注解配置元信息
    • API 配置元信息
  • 自动模式- 实现方提供依赖自动关联的方式,按照內建的注入规则
    • Autowiring(自动绑定):no、byName、byType、constructor

3. Spring IoC 依赖来源

  • 自定义 Bean
  • 容器內建 Bean 对象
  • 容器內建依赖

4. Spring IoC 配置元信息

  • Bean 定义配置

    • 基于 XML 文件
    • 基于 Properties 文件
    • 基于 Java 注解
    • 基于 Java API(专题讨论)
  • IoC 容器配置

    • 基于 XML 文件
    • 基于 Java 注解
    • 基于 Java API (专题讨论)
  • 外部化属性配置

    • 基于Java 注解,@Value 注解

5. Spring IoC 容器

  • BeanFactory 是 Spring 底层 IoC 容器。
  • ApplicationContext 是具备应用特性的 BeanFactory 超集。

ApplicationContext 除了IoC 容器角色,还有提供:

  • 面向切面(AOP)
  • 配置元信息(Configuration Metadata)
  • 资源管理(Resources)
  • 事件(Events)
  • 国际化(i18n)
  • 注解(Annotations)
  • Environment 抽象(Environment Abstraction)
public interface ApplicationContext extends EnvironmentCapable,
     ListableBeanFactory, HierarchicalBeanFactory, MessageSource, 
    ApplicationEventPublisher, ResourcePatternResolver {
}

6. Spring 应用上下文

ApplicationContext

https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-introduction

7. Spring IoC 容器生命周期

  • 启动
  • 运行
  • 停止
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        } catch (BeansException ex) {
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        } finally {
            resetCommonCaches();
        }
    }
}

8. 面试题精选

问题1:什么是 Spring IoC 容器?

问题2:BeanFactory 与FactoryBean?

  • BeanFactory 是IoC 底层容器。
  • FactoryBean 是创建Bean 的一种方式,帮助实现复杂的初始化逻辑。

问题3:Spring IoC 容器启动时做了哪些准备?

IoC 配置元信息读取和解析、IoC 容器生命周期、Spring 事件发布、国际化等,更多答案将在后续专题章节逐一讨论


每天用心记录一点点。内容也许不重要,但习惯很重要!

posted on 2020-02-11 21:36  binarylei  阅读(637)  评论(0编辑  收藏  举报

导航