文章目录
- Spring IOC容器概述
- Spring IoC依赖查找:依赖注入还不够吗?依赖查找存在的价值几何?
- Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
- Spring IoC依赖来源:依赖注入和查找的对象来自于哪里?
- Spring IoC配置元信息:Spring IoC有哪些配置元信息?它们的进化过程是怎样的?
- BeanFactory 和 ApplicationContext 谁才是 Spring IoC 容器?
- Spring应用上下文:ApplicationContext除了IoC容器角色,还提供哪些特性?
- 使用Spring IoC容器:选BeanFactory还是ApplicationContext?
- Spring IoC容器生命周期:IoC容器启停过程中发生了什么?
- 面试题
Spring IOC容器概述
Spring IoC依赖查找:依赖注入还不够吗?依赖查找存在的价值几何?
- 根据 Bean 名称查找
• 实时查找
• 延迟查找
/**
* 延迟查找:使用ObjectFactory进行包装
**/
public void lookupInLazy(BeanFactory beanFactory) {
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
System.out.println("延迟查找:" + user);
}
/**
* 实时查找:使用ObjectFactory进行包装
**/
public void lookupInRealTime(BeanFactory beanFactory) {
User user = (User) beanFactory.getBean("user");
System.out.println("实时查找:" + user);
}
- 根据 Bean 类型查找
• 单个 Bean 对象
• 集合 Bean 对象
/**
* ListableBeanFactory 查找集合 Bean 对象
**/
public 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);
}
}
/**
* 实时查找:单个 Bean 对象
**/
public void lookupByType(BeanFactory beanFactory) {
User user = beanFactory.getBean(User.class);
System.out.println("实时查找:" + user);
}
- 根据 Bean 名称 + 类型查找
- 根据 Java 注解查找
• 单个 Bean 对象
• 集合 Bean 对象
/**
* 通过注解查找对象
**/
public void lookupByAnnotationType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println("查找标注 @Super 所有的 User 集合对象:" + users);
}
}
Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
- 根据 Bean 名称注入
- 根据 Bean 类型注入
• 单个 Bean 对象
• 集合 Bean 对象
<bean id="userRepository" class="org.wangjzm.thinking.in.spring.ioc.overview.repository.UserRepository"
autowire="byType"> <!-- Auto-Wiring -->
<!-- 手动配置 -->
<!-- <property name="users">-->
<!-- <util:list>-->
<!-- <ref bean="superUser" />-->
<!-- <ref bean="user" />-->
<!-- </util:list>-->
<!-- </property>-->
</bean>
- 注入容器內建 Bean 对象
- 注入非 Bean 对象
- 注入类型
• 实时注入
• 延迟注入
Spring IoC依赖来源:依赖注入和查找的对象来自于哪里?
/**
* UserRepository 实体类
**/
public class UserRepository {
private Collection<User> users; // 自定义 Bean
private BeanFactory beanFactory; // 內建非 Bean 对象(依赖)
private ObjectFactory<ApplicationContext> objectFactory;
public Collection<User> getUsers() {
return users;
}
public void setUsers(Collection<User> users) {
this.users = users;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
public ObjectFactory<ApplicationContext> getObjectFactory() {
return objectFactory;
}
public void setObjectFactory(ObjectFactory<ApplicationContext> objectFactory) {
this.objectFactory = objectFactory;
}
}
-
自定义 Bean
-
容器內建 Bean 对象
-
容器內建依赖
public class DependencyInjectionDemo {
public static void main(String[] args) {
// 配置 XML 配置文件
// 启动 Spring 应用上下文
// BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
// 依赖来源一:自定义 Bean
UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
// System.out.println(userRepository.getUsers());
// 依赖来源二:依赖注入(內建依赖)
System.out.println(userRepository.getBeanFactory());
ObjectFactory userFactory = userRepository.getObjectFactory();
// true
System.out.println(userFactory.getObject() == applicationContext);
// 依赖查找(错误)
// System.out.println(beanFactory.getBean(BeanFactory.class));
// 依赖来源三:容器內建 Bean
Environment environment = applicationContext.getBean(Environment.class);
System.out.println("获取 Environment 类型的 Bean:" + environment);
}
private static void whoIsIoCContainer(UserRepository userRepository, ApplicationContext applicationContext) {
// ConfigurableApplicationContext <- ApplicationContext <- BeanFactory
// ConfigurableApplicationContext#getBeanFactory()
// ApplicationContext is BeanFactory
// false,这个表达式为什么不会成立?
// 原因:userRepository.getBeanFactory()获取的BeanFactory和aplicationContext
// 是两个不同的对象,aplicationContext中组合了BeanFactory,类似于代理,之后从
// applicationContext中调用getBean()方法其实就是调用组合对象BeanFactory的getBean()方法
System.out.println(userRepository.getBeanFactory() == applicationContext);
}
Spring IoC配置元信息:Spring IoC有哪些配置元信息?它们的进化过程是怎样的?
- Bean 定义配置
• 基于 XML 文件
• 基于 Properties 文件
• 基于 Java 注解
• 基于 Java API(专题讨论) - IoC 容器配置
• 基于 XML 文件
• 基于 Java 注解
• 基于 Java API (专题讨论) - 外部化属性配置
• 基于 Java 注解
BeanFactory 和 ApplicationContext 谁才是 Spring IoC 容器?
两者都是,原因是上上章节代码中最后注释:
userRepository.getBeanFactory()获取的BeanFactory和aplicationContext是两个不同的对象aplicationContext中组合了BeanFactory,类似于代理,之后从applicationContext中调用getBean()方法其实就是调用组合对象BeanFactory的getBean()方法。
Spring应用上下文:ApplicationContext除了IoC容器角色,还提供哪些特性?
• 面向切面(AOP)
• 配置元信息(Configuration Metadata)
• 资源管理(Resources)
• 事件(Events)
• 国际化(i18n)
• 注解(Annotations)
• Environment 抽象(Environment Abstraction)
使用Spring IoC容器:选BeanFactory还是ApplicationContext?
- BeanFactory 是 Spring 底层 IoC 容器
- ApplicationContext 是具备应用特性的 BeanFactory 超集
Spring IoC容器生命周期:IoC容器启停过程中发生了什么?
之后再做详细分析。
面试题
-
什么是 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 事件发布、国
际化等,更多答案将在后续专题章节逐一讨论