第三章 Spring IoC 容器概述

第三章 Spring IoC 容器概述

依赖查找

  1. 单一类型 实时查找
<bean id="user" class="org.xxx.domain.User">
    <property name="id" value="1"/>
    <property name="name" value="法外狂徒张三"/>
</bean>
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");

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

User user = beanFactory.getBean(User.class);
  1. 单一类型 延迟查找
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
    <property name="targetBeanName" value="user"/>
</bean>
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
  1. 集合类型 实时查找
<bean id="superUser" class="org.xxx.domain.SuperUser" parent="user"
        primary="true">
    <property name="address" value="杭州"/>
</bean>
if (beanFactory instanceof ListableBeanFactory) {
    ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
    Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);

    Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
}

依赖注入

  1. xml 手动注入
    <bean id="userRepository" class="com.xxx.repository.UserRepository">
        <!-- 手动配置 -->
        <property name="users">
            <util:list>
                <ref bean="superUser"/>
                <ref bean="user"/>
            </util:list>
        </property>
    </bean>
public class UserRepository {

    private Collection<User> users; // 自定义 Bean

    public Collection<User> getUsers() {
        return users;
    }

    public void setUsers(Collection<User> users) {
        this.users = users;
    }
}
  1. xml 自动注入
    <bean id="userRepository" class="com.xxx.repository.UserRepository"
          autowire="byType"> <!-- Auto-Wiring -->
    </bean>
public class UserRepository {

    private Collection<User> users; // 自定义 Bean

    public Collection<User> getUsers() {
        return users;
    }

    public void setUsers(Collection<User> users) {
        this.users = users;
    }
}

    // Test Class
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
        // 依赖来源一:自定义 Bean
        UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
        System.out.println(userRepository.getUsers());
    }
  1. 容器内建 bean 对象
public class UserRepository {
    private BeanFactory beanFactory; // 內建非 Bean 对象(依赖)

    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }
}

    public static void main(String[] args) {

        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
        UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
        // 依赖来源二:依赖注入(內建依赖)
        System.out.println(userRepository.getBeanFactory()); // org.springframework.beans.factory.support.DefaultListableBeanFactory@6b143ee9
        System.out.println(userRepository.getBeanFactory() == applicationContext.getBeanFactory()); // true

        // 依赖查找
        System.out.println(applicationContext.getBean(BeanFactory.class)); // No qualifying bean of type 'org.springframework.beans.factory.BeanFactory' available

        // 依赖来源是否一致?
        // 为何依赖注入可以得到,而依赖查找得不到 beanFactory 对象?
    }

非实时注入

public class UserRepository {

    private ObjectFactory<ApplicationContext> objectFactory;

    public ObjectFactory<ApplicationContext> getObjectFactory() {
        return objectFactory;
    }

    public void setObjectFactory(ObjectFactory<ApplicationContext> objectFactory) {
        this.objectFactory = objectFactory;
    }
}

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
        UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
        ObjectFactory userFactory = userRepository.getObjectFactory();
        System.out.println(userFactory.getObject() == applicationContext); // true
    }
  1. 依赖来源
  • 自定义 Bean 对象
    • UserRepository
  • 容器内建 Bean 对象
    • Environment
    • 支持依赖查找
  • 容器内建依赖(非 Bean 对象)
    • BeanFactory
    • 可以依赖注入得到,但依赖查找不到
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
        // 依赖来源三:容器內建 Bean
        Environment environment = applicationContext.getBean(Environment.class);
        System.out.println("获取 Environment 类型的 Bean:" + environment); // StandardEnvironment
    }

配置元信息

  • Bean 定义配置
    • 基于 XML 文件
    • 基于 Java 注解
    • 基于 Properties 文件
    • 基于 Java API
  • Ioc 容器配置
    • 基于 XML 文件
    • 基于 Java 注解
    • 基于 Java API
  • 外部化属性配置
    • 基于 Java 注解

Bean 定义 – 基于 XML 文件


Bean 定义 – 基于 Java 注解


Bean 定义 – 基于 Properties 文件


BeanFactory 和 ApplicationContext 谁才是 Spring ioc 容器 ?

The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:

  • Easier integration with Spring’s AOP features
  • Message resource handling (for use in internationalization)
  • Event publication
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.
    In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container.

https://docs.spring.io/spring/docs/5.3.0-SNAPSHOT/spring-framework-reference/core.html#beans-introduction


public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    @Nullable
    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    @Nullable
    private Boolean allowBeanDefinitionOverriding;
    @Nullable
    private Boolean allowCircularReferences;
    @Nullable
    private DefaultListableBeanFactory beanFactory;
    private final Object beanFactoryMonitor = new Object();

    public AbstractRefreshableApplicationContext() {
    }

    // ...
}

看似继承,实际上是组合!!!类似于代理


ApplicationContext

在这里插入图片描述


BeanFactory 和 ApplicationContext 的应用

public class BeanFactoryAsIoCContainerDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        // XML 配置文件 ClassPath 路径
        String location = "classpath:/META-INF/dependency-lookup-context.xml";
        // 加载配置
        int beanDefinitionsCount = reader.loadBeanDefinitions(location);
        System.out.println("Bean 定义加载的数量:" + beanDefinitionsCount);
        // 依赖查找集合对象
        lookupCollectionByType(beanFactory);
    }

    private static void lookupCollectionByType(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
            System.out.println("查找到的所有的 User 集合对象:" + users);
        }
    }

}
@Configuration
public class AnnotationApplicationContextAsIoCContainerDemo {

    /**
     * 通过 Java 注解的方式,定义了一个 Bean
     */
    @Bean
    public User user() {
        User user = new User();
        user.setId(1L);
        user.setName("张三");
        return user;
    }

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 AnnotationApplicationContextAsIoCContainerDemo 作为配置类(Configuration Class)
        applicationContext.register(AnnotationApplicationContextAsIoCContainerDemo.class);
        // 启动应用上下文
        applicationContext.refresh();
        // 依赖查找集合对象
        lookupCollectionByType(applicationContext);
        // 关闭应用上下文
        applicationContext.close();
    }

    private static void lookupCollectionByType(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
            System.out.println("查找到的所有的 User 集合对象:" + users);
        }
    }

}

Ioc 容器的启动、运行和停止

启动

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    // ...
    public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

    // ...
}

总结

什么是 Spring Ioc 容器?

Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean.


BeanFactory 与 FactoryBean?

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



Spring IoC 容器启动时做了哪些准备?

  • IoC 配置元信息读取与解析
  • IoC 容器生命周期
  • Spring 事件发布
  • 国际化
  • 等等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值