01 依赖注入的模式和类型
- 手动
- xml配置
- Java注解配置元信息
- API配置元信息(日常开发很少用,比较底层的知识点)
- 自动绑定
- Autowiring
02 自动绑定 Autowiring
no 默认,不推荐,有危险
byName
byType 多个的时候可以设置primary来解决
constructor 构造器 是特殊的byType类型
03 自动绑定模式
04 自动绑定限制和不足
参照官方文档
不够精确
用的非常少## 05 setter注入 - Autowiring
- 手动
- xml
- java 注解
- API配置元信息
- 自动
- Java注解配置元信息
- @Autowired
- @Resource
- @Inject(可选)
- @Autowired User user;会忽略到静态字段
08 方法注入
- Java注解配置元信息
- @Autowired
- @Resource
- @Inject(可选)
- @Bean
- @Autowired public void user(User user){…}
09 回调注入
- Aware系列接口回调-内建的
- 自动模式
- BeanFactoryAware
- ApplicationContextAware
- BeanNameAware
- MessageSourceAware
- ApplicationEventPublisherAware
- EmbeddedValueResolverAware
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {
private static BeanFactory beanFactory;
private static ApplicationContext applicationContext;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
context.register(AwareInterfaceDependencyInjectionDemo.class);
// 启动 Spring 应用上下文
context.refresh();
System.out.println(beanFactory == context.getBeanFactory());
System.out.println(applicationContext == context);
// 显示地关闭 Spring 应用上下文
context.close();
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext;
}
}
- 自动模式
- class MyBean implements BeanFactoryAware{…}
010 依赖注入类型选择
- 低依赖:构造器
- 多依赖:setter注入
- 便利性:字段注入
- 声明类:方法注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47public class ApiDependencySetterInjectionDemo {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 生成 UserHolder 的 BeanDefinition
BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();
// 注册 UserHolder 的 BeanDefinition
applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找并且创建 Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
/**
* 为 {@link UserHolder} 生成 {@link BeanDefinition}
*
* @return
*/
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
definitionBuilder.addPropertyReference("user", "superUser");
return definitionBuilder.getBeanDefinition();
}
// @Bean
// public UserHolder userHolder(User user) { // superUser -> primary = true
// UserHolder userHolder = new UserHolder();
// userHolder.setUser(user);
// return userHolder;
// }
}011 基础类型注入
012 集合类型注入
- 数组:原生 标量 常规
- 集合:Collection List Set
Map Properties
013 限定注入
- 使用@Qualifier限定
- 通过bean名称限定
- 通过分组限定
- 基于注解@Qualifier扩展限定
- 自定义注解-如spring cloud @LoadBalanced
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class QualifierAnnotationDependencyInjectionDemo {
private User user; // superUser -> primary =true
// 指定 Bean 名称或 ID
private User namedUser;
// 整体应用上下文存在 4 个 User 类型的 Bean:
// superUser
// user
// user1 -> @Qualifier
// user2 -> @Qualifier
private Collection<User> allUsers; // 2 Beans = user + superUser
private Collection<User> qualifiedUsers; // 2 Beans = user1 + user2 -> 4 Beans = user1 + user2 + user3 + user4
private Collection<User> groupedUsers; // 2 Beans = user3 + user4
// 进行逻辑分组
public User user1() {
return createUser(7L);
}
// 进行逻辑分组
public static User user2() {
return createUser(8L);
}
public static User user3() {
return createUser(9L);
}
public static User user4() {
return createUser(10L);
}
private static User createUser(Long id) {
User user = new User();
user.setId(id);
return user;
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(QualifierAnnotationDependencyInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
QualifierAnnotationDependencyInjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencyInjectionDemo.class);
// TODO: 2020/12/19 为什么没有user1这个bean??
// 期待输出 superUser Bean
System.out.println("demo.user = " + demo.user);
// 期待输出 user Bean
System.out.println("demo.namedUser = " + demo.namedUser);
// 期待输出 superUser user user1 user2
System.out.println("demo.allUsers = " + demo.allUsers);
// 期待输出 user1 user2
System.out.println("demo.qualifiedUsers = " + demo.qualifiedUsers);
// 期待输出 user3 user4
System.out.println("demo.groupedUsers = " + demo.groupedUsers);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}014 延迟依赖注入
- 自定义注解-如spring cloud @LoadBalanced
- ObjectFactory 只能二选一 get方法获取
- 单一
- 集合
- ObjectProvider(推荐) 减少避免相关的一些异常
- 单一
- 集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class LazyAnnotationDependencyInjectionDemo {
private User user; // 实时注入
private ObjectProvider<User> userObjectProvider; // 延迟注入
private ObjectFactory<Set<User>> usersObjectFactory;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);
// 期待输出 superUser Bean
System.out.println("demo.user = " + demo.user);
// 期待输出 superUser Bean
System.out.println("demo.userObjectProvider = " + demo.userObjectProvider.getObject()); // 继承 ObjectFactory
// 期待输出 superUser user Beans
System.out.println("demo.usersObjectFactory = " + demo.usersObjectFactory.getObject());
demo.userObjectProvider.forEach(System.out::println);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}015 依赖处理过程
- 入口 DefaultListableBeanFactory#resolveDependency
- 依赖描述符 DependencyDescriptor
- 自动绑定候选对象处理器 AutowireCandidateResolver
016 autowired注入原理
- 元信息解析
- postProcessMergedBeanDefinition()
- 依赖查找
- 依赖注入(字段,方法)
- postProcessProperties() inject() 还包括依赖查找的处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46public class AnnotationDependencyFieldInjectionDemo {
private
// static // @Autowired 会忽略掉静态字段
UserHolder userHolder;
private UserHolder userHolder2;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(AnnotationDependencyFieldInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载 XML 资源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);
// @Autowired 字段关联
UserHolder userHolder = demo.userHolder;
System.out.println(userHolder);
System.out.println(demo.userHolder2);
System.out.println(userHolder == demo.userHolder2);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
public UserHolder userHolder(User user) {
return new UserHolder(user);
}
}017 inject注入原理
- postProcessProperties() inject() 还包括依赖查找的处理
- 如果jsr-330存在于classpath中,复用AutowiredAnnotationBeanPostProcessor实现
018 Java通用注解注入
- CommonAnnotationBeanPostProcessor
- 基于实现
- AutowiredAnnotationBeanPostProcessor
- 自定义实现
来源 | spring bean对象 | 生命周期管理 | 配置元信息 | 使用场景 |
---|---|---|---|---|
Spring BeanDefinition | 是 | 是 | 有 | 依赖查找 依赖注入 |
单体对象 | 是 | 否 | 无 | 依赖查找 依赖注入 |
Resolvable Dependency | 否 | 否 | 无 | 依赖注入 |
1 | public class DependencySourceDemo { |
- Spring BeanDefinition作为依赖来源
- 元数据:BeanDefinition
- 注册:BeanDefinitionRegistry#registerBeanDefinition
- 类型:延迟 非延迟
- 顺序:Bean生命周期顺序按照注册顺序
- 单例对象作为依赖来源
- 来源:外部Java对象(不一定是pojo)
- 注册:SingletonBeanRegistry#registerSingleton
- 限制:无生命周期管理 无法延迟初始化Bean
- 非Spring IOC托管对象作为依赖来源–ResolvableDependency
- 注册:ConfigurableListableBeanFactory#registerResolvableDependency
- 限制:无生命周期管理
无法实现延迟初始化bean 无法通过依赖查找
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31public class ResolvableDependencySourceDemo {
private String value;
public void init() {
System.out.println(value);
}
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(ResolvableDependencySourceDemo.class);
applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
// 注册 Resolvable Dependency
beanFactory.registerResolvableDependency(String.class, "Hello,World");
});
// 启动 Spring 应用上下文
applicationContext.refresh();
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}
- 外部化配置作为依赖来源
- 类型:非常规spring对象
- 限制:无生命周期管理
无法实现延迟初始化bean 无法通过依赖查找
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ExternalConfigurationDependencySourceDemo {
private Long id;
private String name;
private Resource resource;
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类) -> Spring Bean
applicationContext.register(ExternalConfigurationDependencySourceDemo.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 依赖查找 ExternalConfigurationDependencySourceDemo Bean
ExternalConfigurationDependencySourceDemo demo = applicationContext.getBean(ExternalConfigurationDependencySourceDemo.class);
System.out.println("demo.id = " + demo.id);
System.out.println("demo.name = " + demo.name);
System.out.println("demo.resource = " + demo.resource);
// 显示地关闭 Spring 应用上下文
applicationContext.close();
}
}021 单例对象能在IOC容器启动后注册么
可以的,单例对象的注册与BeanDefinition不同,BeanDefinition会被ConfigurableListableBeanFactory#freezeConfiguration()方法影响,
从而冻结注册,单例对象则没有这个限制。