1.写在前面
前面的博客我们已经写了Spring的依赖查找,这篇博客我们来了解写Spring的依赖注入。
2.依赖注入的模式和类型
手动模式 - 配置或者编程的方式, 提前安排注入规则
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
自动模式 - 实现方提供依赖自动关联的方式, 按照內建的注入规则
- Autowiring( 自动绑定)
依赖注入的类型
3.自动绑定( Autowiring)
官方说明
- The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext.
- Spring 容器可以自动装配协作 bean 之间的关系。 您可以让 Spring 通过检查 ApplicationContext 的内容自动为您的 bean 解析协作者(其他 bean)。
优点
- Autowiring can significantly reduce the need to specify properties or constructor arguments.(自动装配可以显着减少指定属性或构造函数参数的需要。)
- Autowiring can update a configuration as your objects evolve.(随着对象的发展,自动装配可以更新配置。)
4.自动绑定( Autowiring) 模式
5.自动绑定( Autowiring) 限制和不足
官方说明
- Limitations and Disadvantages of Autowiring 小节
6.Setter 方法注入
实现方法
- 手动模式
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
- 自动模式
- byName
- byType
下面我们来展示各种代码,具体的如下:
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="org.learn.spring.dependency.injection.UserHolder">
<property name="user" ref="superUser"/>
</bean>
</beans>
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
// 基于 xml 的setter依赖注入的示例
public class XmlDependencySetterInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlResourcePath = "classpath:/META-INF/dependency-setter-injection.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 创建依赖查找并且创建Bean
UserHolder userHolder = beanFactory.getBean(UserHolder.class);
System.out.println(userHolder);
}
}
Java 注解配置元信息
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Map;
// 基于 Annotation 的setter依赖注入的示例
public class AnnotationDependencySetterInjectionDemo {
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类
applicationContext.register(AnnotationDependencySetterInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 创建依赖查找并且创建Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示的关闭spring应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user){
UserHolder userHolder = new UserHolder();
userHolder.setUser(user);
return userHolder;
}
}
API 配置元信息
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
// 基于 API 的setter依赖注入的示例
public 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);
// 启动应用上下文
applicationContext.refresh();
// 创建依赖查找并且创建Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示的关闭spring应用上下文
applicationContext.close();
}
// 为UserHolder生成BeanDefinition
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
beanDefinitionBuilder.addPropertyReference("user", "superUser");
return beanDefinitionBuilder.getBeanDefinition();
}
}
byName
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="org.learn.spring.dependency.injection.UserHolder" autowire="byName"/>
</beans>
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
// byName AutoWring 依赖 setter方法注入示例
public class AutoWringByNameDependencySetterInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlResourcePath = "classpath:/META-INF/autowring-dependency-setter-injection.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 创建依赖查找并且创建Bean
UserHolder userHolder = beanFactory.getBean(UserHolder.class);
System.out.println(userHolder);
}
}
byType
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="org.learn.spring.dependency.injection.UserHolder" autowire="byType"/>
</beans>
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
// byName AutoWring 依赖 setter方法注入示例
public class AutoWringByNameDependencySetterInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlResourcePath = "classpath:/META-INF/autowring-dependency-setter-injection.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 创建依赖查找并且创建Bean
UserHolder userHolder = beanFactory.getBean(UserHolder.class);
System.out.println(userHolder);
}
}
7.构造器注入
实现方法
- 手动模式
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
- 自动模式
- constructor
下面来展示示例代码
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="org.learn.spring.dependency.injection.UserHolder">
<constructor-arg name="user" ref="superUser"/>
</bean>
</beans>
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
// 基于 xml 的Constructor依赖注入的示例
public class XmlDependencyConstructorInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlResourcePath = "classpath:/META-INF/dependency-constructor-injection.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 创建依赖查找并且创建Bean
UserHolder userHolder = beanFactory.getBean(UserHolder.class);
System.out.println(userHolder);
}
}
Java 注解配置元信息
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
// 基于 Annotation 的Constructor依赖注入的示例
public class AnnotationDependencyConstructorInjectionDemo {
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类
applicationContext.register(AnnotationDependencyConstructorInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 创建依赖查找并且创建Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示的关闭spring应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user){
return new UserHolder(user);
}
}
API 配置元信息
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// 基于 API 的Constructor依赖注入的示例
public class ApiDependencyConstructorInjectionDemo {
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);
// 启动应用上下文
applicationContext.refresh();
// 创建依赖查找并且创建Bean
UserHolder userHolder = applicationContext.getBean(UserHolder.class);
System.out.println(userHolder);
// 显示的关闭spring应用上下文
applicationContext.close();
}
// 为UserHolder生成BeanDefinition
private static BeanDefinition createUserHolderBeanDefinition() {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
beanDefinitionBuilder.addConstructorArgReference("superUser");
return beanDefinitionBuilder.getBeanDefinition();
}
}
constructor
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="org.learn.spring.dependency.injection.UserHolder" autowire="constructor"/>
</beans>
package org.learn.spring.dependency.injection;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
// constructor AutoWring 依赖 constructor方法注入示例
public class AutoWringConstructorDependencyConstructorInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlResourcePath = "classpath:/META-INF/autowring-dependency-constructor-injection.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 创建依赖查找并且创建Bean
UserHolder userHolder = beanFactory.getBean(UserHolder.class);
System.out.println(userHolder);
}
}
8.字段注入
实现方法
- 手动模式
- Java 注解配置元信息
- @Autowired
- @Resource
- @Inject( 可选)
具体的代码如下:
@Autowired
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
// 基于 Annotation 的Field依赖注入的示例
public class AnnotationDependencyFieldInjectionDemo {
@Autowired // @Autowired 会忽略静态字段
private UserHolder userHolder;
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);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);
// 通过@Autowired字段关联
UserHolder userHolder = demo.userHolder;
System.out.println(userHolder);
// 显示的关闭spring应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user){
return new UserHolder(user);
}
}
@Resource
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.annotation.Resource;
// 基于 Annotation 的Field依赖注入的示例
public class AnnotationDependencyFieldInjectionDemo {
@Autowired // @Autowired 会忽略静态字段
private UserHolder userHolder;
@Resource
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);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
AnnotationDependencyFieldInjectionDemo demo = applicationContext.getBean(AnnotationDependencyFieldInjectionDemo.class);
// 通过@Autowired字段关联
UserHolder userHolder = demo.userHolder;
System.out.println(userHolder);
// 通过@Resource字段关联
UserHolder userHolder2 = demo.userHolder2;
System.out.println(userHolder2);
// 显示的关闭spring应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user){
return new UserHolder(user);
}
}
9.方法注入
实现方法
- 手动模式
- Java 注解配置元信息
- @Autowired
- @Resource
- @Inject( 可选)
- @Bean
- Java 注解配置元信息
具体的代码如下:
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.annotation.Resource;
// 基于 Annotation 的Method依赖注入的示例
public class AnnotationDependencyMethodInjectionDemo {
private UserHolder userHolder;
private UserHolder userHolder2;
@Autowired
public void init1(UserHolder userHolder){
this.userHolder = userHolder;
}
@Resource
public void init2(UserHolder userHolder2){
this.userHolder2 = userHolder2;
}
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyMethodInjectionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
AnnotationDependencyMethodInjectionDemo demo = applicationContext.getBean(AnnotationDependencyMethodInjectionDemo.class);
// 通过@Autowired字段关联
UserHolder userHolder = demo.userHolder;
System.out.println(userHolder);
// 通过@Resource字段关联
UserHolder userHolder2 = demo.userHolder2;
System.out.println(userHolder2);
System.out.println(userHolder == userHolder2);
// 显示的关闭spring应用上下文
applicationContext.close();
}
@Bean
public UserHolder userHolder(User user){
return new UserHolder(user);
}
}
10.接口回调注入
Aware 系列接口回调
自动模式
具体的代码如下:
package org.learn.spring.dependency.injection;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// 基于 Aware 的接口回调依赖注入的示例
public 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);
// 启动应用上下文
context.refresh();
System.out.println(beanFactory == context.getBeanFactory());
System.out.println(applicationContext == context);
// 显示的关闭spring应用上下文
context.close();
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext;
}
}
11.依赖注入类型选择
注入选型
- 低依赖: 构造器注入
- 多依赖: Setter 方法注入
- 便利性: 字段注入
- 声明类: 方法注入
12.基础类型注入
基础类型
-
原生类型( Primitive) : boolean、 byte、 char、 short、 int、 float、 long、 double
-
标量类型( Scalar) : Number、 Character、 Boolean、 Enum、 Locale、 Charset、 Currency、
Properties、 UUID
-
常规类型( General) : Object、 String、 TimeZone、 Calendar、 Optional 等
-
Spring 类型: Resource、 InputSource、 Formatter 等
具体的代码如下:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="org.learn.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value="胡桃"/>
<property name="city" value="HANGZHOU"/>
<property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
</bean>
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>
<bean id="superUser" class="org.learn.spring.ioc.overview.domain.SuperUser" parent="user" primary="true">
<property name="address" value="璃月"/>
</bean>
</beans>
package org.learn.spring.ioc.overview.domain;
import org.learn.spring.ioc.overview.enums.City;
import org.springframework.core.io.Resource;
import java.util.Arrays;
import java.util.List;
// 用户类
public class User {
private Long id;
private String name;
private City city;
private Resource configFileLocation;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public Resource getConfigFileLocation() {
return configFileLocation;
}
public void setConfigFileLocation(Resource configFileLocation) {
this.configFileLocation = configFileLocation;
}
public static User createUser(){
User user = new User();
user.setId(1L);
user.setName("温蒂");
return user;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", city=" + city +
", configFileLocation=" + configFileLocation +
'}';
}
}
package org.learn.spring.ioc.overview.dependency.lookup;
import org.learn.spring.ioc.overview.annotation.Super;
import org.learn.spring.ioc.overview.domain.SuperUser;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Map;
// 依赖查找的示例
public class DependencyLookupDemo {
public static void main(String[] args) {
// 配置XML 配置文件
// 启动spring的应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");
// 1.按照名称查找
lookupInRealTime(beanFactory);
lookupInLazy(beanFactory);
// 2.按照类型查找
lookupByType(beanFactory);
lookupCollectionByType(beanFactory);
// 3.按照类型和名称查找
lookupByNameAndType(beanFactory);
// 4.通过注解查找对象
lookupCollectionByAnnotation(beanFactory);
}
// 实时查找
private static void lookupInRealTime(BeanFactory beanFactory) {
User user = (User) beanFactory.getBean("user");
System.out.println("实时查找:" + user);
}
// 延时查找
private static void lookupInLazy(BeanFactory beanFactory) {
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
System.out.println("延时查找:" + user);
}
// 按照类型查找
private static void lookupByType(BeanFactory beanFactory) {
User user = beanFactory.getBean(User.class);
System.out.println("按照类型查找单一对象:" + user);
}
// 按照类型查找集合
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);
}
}
// 按照类型和名称
private static void lookupByNameAndType(BeanFactory beanFactory) {
User user = beanFactory.getBean("user", User.class);
System.out.println("按照类型和名称查找:" + user);
}
// 按照注解查找集合对象
private static void lookupCollectionByAnnotation(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println("按照注解查找到的所有的标注@SuperUser User 集合对象:" + users);
}
}
}
13.集合类型注入
集合类型
- 数组类型( Array) : 原生类型、 标量类型、 常规类型、 Spring 类型
- 集合类型( Collection)
- Collection: List、 Set( SortedSet、 NavigableSet、 EnumSet)
- Map: Properties
具体的代码如下:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="org.learn.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value="胡桃"/>
<property name="city" value="HANGZHOU"/>
<property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
<property name="workCities" value="BEIJING,HANGZHOU"/>
<property name="lifeCities">
<list>
<value>BEIJING</value>
<value>HANGZHOU</value>
<value>SHANGHAI</value>
</list>
</property>
</bean>
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>
<bean id="superUser" class="org.learn.spring.ioc.overview.domain.SuperUser" parent="user" primary="true">
<property name="address" value="璃月"/>
</bean>
</beans>
package org.learn.spring.ioc.overview.domain;
import org.learn.spring.ioc.overview.enums.City;
import org.springframework.core.io.Resource;
import java.util.Arrays;
import java.util.List;
// 用户类
public class User {
private Long id;
private String name;
private City city;
private City[] workCities;
private List<City> lifeCities;
private Resource configFileLocation;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public Resource getConfigFileLocation() {
return configFileLocation;
}
public void setConfigFileLocation(Resource configFileLocation) {
this.configFileLocation = configFileLocation;
}
public City[] getWorkCities() {
return workCities;
}
public void setWorkCities(City[] workCities) {
this.workCities = workCities;
}
public List<City> getLifeCities() {
return lifeCities;
}
public void setLifeCities(List<City> lifeCities) {
this.lifeCities = lifeCities;
}
public static User createUser(){
User user = new User();
user.setId(1L);
user.setName("温蒂");
return user;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", city=" + city +
", workCities=" + Arrays.toString(workCities) +
", lifeCities=" + lifeCities +
", configFileLocation=" + configFileLocation +
'}';
}
}
package org.learn.spring.ioc.overview.dependency.lookup;
import org.learn.spring.ioc.overview.annotation.Super;
import org.learn.spring.ioc.overview.domain.SuperUser;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Map;
// 依赖查找的示例
public class DependencyLookupDemo {
public static void main(String[] args) {
// 配置XML 配置文件
// 启动spring的应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");
// 1.按照名称查找
lookupInRealTime(beanFactory);
lookupInLazy(beanFactory);
// 2.按照类型查找
lookupByType(beanFactory);
lookupCollectionByType(beanFactory);
// 3.按照类型和名称查找
lookupByNameAndType(beanFactory);
// 4.通过注解查找对象
lookupCollectionByAnnotation(beanFactory);
}
// 实时查找
private static void lookupInRealTime(BeanFactory beanFactory) {
User user = (User) beanFactory.getBean("user");
System.out.println("实时查找:" + user);
}
// 延时查找
private static void lookupInLazy(BeanFactory beanFactory) {
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
System.out.println("延时查找:" + user);
}
// 按照类型查找
private static void lookupByType(BeanFactory beanFactory) {
User user = beanFactory.getBean(User.class);
System.out.println("按照类型查找单一对象:" + user);
}
// 按照类型查找集合
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);
}
}
// 按照类型和名称
private static void lookupByNameAndType(BeanFactory beanFactory) {
User user = beanFactory.getBean("user", User.class);
System.out.println("按照类型和名称查找:" + user);
}
// 按照注解查找集合对象
private static void lookupCollectionByAnnotation(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println("按照注解查找到的所有的标注@SuperUser User 集合对象:" + users);
}
}
}
14.限定注入
使用注解 @Qualifier 限定
- 通过 Bean 名称限定
- 通过分组限定
基于注解 @Qualifier 扩展限定
- 自定义注解 - 如 Spring Cloud @LoadBalanced
具体的代码如下:
package org.learn.spring.dependency.injection.annotation;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 用户组 注解 扩展 @Qualifier
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface UserGroup {
}
package org.learn.spring.dependency.injection;
import org.learn.spring.dependency.injection.annotation.UserGroup;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Collection;
// Qualifier 注解依赖注入
public class QualifierAnnotationDependencyInjectionDemo {
@Autowired
private User user; // superUser -> primary
@Autowired
@Qualifier(value = "user") // 指定Bean 名称或者id注入
private User nameUser;
// 整体应用上下文存在4个 User类型的Bean:
// superUser
// user
// user1 -> @Qualifier
// user2 -> @Qualifier
@Autowired
private Collection<User> allUsers; // 2 Bean superUser + user
@Autowired
@Qualifier
private Collection<User> qualifiedUsers; // 2 Bean = user1 + user2 -> 4 Bean = user1 + user2 + user3 + user4
@Autowired
@UserGroup
private Collection<User> groupedUsers; // 2 Bean = user3 + user4
@Bean
@Qualifier // 进行逻辑分组
public User user1(){
return createUser(7L);
}
@Bean
@Qualifier // 进行逻辑分组
public User user2(){
return createUser(8L);
}
@Bean
@UserGroup
public User user3(){
return createUser(9L);
}
@Bean
@UserGroup
public User user4(){
return createUser(10L);
}
public 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);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
QualifierAnnotationDependencyInjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencyInjectionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.user = " + demo.user);
// 期待输出user Bean
System.out.println("demo.nameUser = " + demo.nameUser);
// 期待输出2 Bean superUser + user
System.out.println("demo.allUsers = " + demo.allUsers);
// 期待输出2 Bean user1 user2
System.out.println("demo.qualifiedUsers = " + demo.qualifiedUsers);
// 期待输出2 Bean user3 user4
System.out.println("demo.groupedUsers = " + demo.groupedUsers);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
15.延迟依赖注入
使用 API ObjectFactory 延迟注入
- 单一类型
- 集合类型
使用 API ObjectProvider 延迟注入( 推荐)
- 单一类型
- 集合类型
具体的代码如下:
package org.learn.spring.dependency.injection;
import org.learn.spring.dependency.injection.annotation.UserGroup;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Collection;
import java.util.Set;
// ObjectProvider 实现延迟依赖注入
public class LazyAnnotationDependencyInjectionDemo {
@Autowired
private User user; // 实时注入
@Autowired
private ObjectProvider<User> userObjectProvider; // 延迟注入
@Autowired
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);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo 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 Bean
System.out.println("demo.usersObjectFactory = " + demo.usersObjectFactory.getObject());
demo.userObjectProvider.stream().forEach(System.out::println);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
16.依赖处理过程
基础知识
- 入口 - DefaultListableBeanFactory#resolveDependency
- 依赖描述符 - DependencyDescriptor
- 自定绑定候选对象处理器 - AutowireCandidateResolver
先来简单的分析下对应的源码,具体的代码如下:
/*
*
descriptor ——依赖项的描述符(字段/方法/构造函数)
requestingBeanName – 声明给定依赖项的 bean 的名称
autowiredBeanNames – 应该将所有自动装配 bean 的名称(用于解析给定的依赖项)添加到的集合
typeConverter – 类型转换器
*/
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
我们先来看第一个参数DependencyDescriptor
依赖的描述符,我们先打开对应的代码,先看对应的属性,具体的如下:
public class DependencyDescriptor extends InjectionPoint implements Serializable {
// 被注入的类、容器
private final Class<?> declaringClass;
// 注入的方法的名称
@Nullable
private String methodName;
// 注入的方法的参数类型
@Nullable
private Class<?>[] parameterTypes;
// 注入的参数的索引
private int parameterIndex;
// 注入的字段的名称
@Nullable
private String fieldName;
// 是否是必须注入的 对应的@Autowired注解中的值
private final boolean required;
// 对应的是@Lazy注解中的值
private final boolean eager;
// 嵌入的层次
private int nestingLevel = 1;
// 包含的类
@Nullable
private Class<?> containingClass;
// 泛型的内容,后面的内容会讲
@Nullable
private transient volatile ResolvableType resolvableType;
// 类型的描述
@Nullable
private transient volatile TypeDescriptor typeDescriptor;
}
上面只是简单的分析了一下,比较模糊,下面我们通过一个简单的例子和debug的方式来帮助我们更深层次的理解,具体的例子如下:
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Set;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.user = " + demo.user);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
我们在DefaultListableBeanFactory#resolveDependency
方法中加入对应的断点,然后Debug,就可以看到如下的截图,看看我们之前猜测的DependencyDescriptor
是否是对的,具体的内容如下:
我们继续拿出之前的代码,具体的如下:
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 这儿是字段注入,所以这个方法直接返回
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// descriptor.getDependencyType() 获取依赖的类型
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
descriptor.getDependencyType()
是获取依赖的类型,具体的内容如下:
public Class<?> getDependencyType() {
// 这里的field 是等于user
if (this.field != null) {
// 这儿的层级是等于1,所以直接返回的user
if (this.nestingLevel > 1) {
Type type = this.field.getGenericType();
for (int i = 2; i <= this.nestingLevel; i++) {
if (type instanceof ParameterizedType) {
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
type = args[args.length - 1];
}
}
if (type instanceof Class) {
return (Class<?>) type;
}
else if (type instanceof ParameterizedType) {
Type arg = ((ParameterizedType) type).getRawType();
if (arg instanceof Class) {
return (Class<?>) arg;
}
}
return Object.class;
}
else {
// 直接返回user
return this.field.getType();
}
}
else {
return obtainMethodParameter().getNestedParameterType();
}
}
由于descriptor.getDependencyType()
返回的是user
类型,所以上面的resolveDependency
的四个if判断的类型都是不满足的,直接走最后一个判断。代码如下:
// 这个方法返回 null,后面再说
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
然后会直接调用doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
方法,具体的内容如下:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter
typeConverter) throws BeansException {
// 只有多次嵌套的时候这儿才不会返回null
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 快捷方式这儿也是没有的,返回的是null
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 这儿返回的是user类型
Class<?> type = descriptor.getDependencyType();
// 这儿返回的也是null,后面我们会讲
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 直接跳到这儿执行
// 这儿判断是否要注入的是多个bean,也是null
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 这儿方法中的beanName 等于的是 annotationDependencyInjectionResolutionDemo 也是被注入的beanName
// type 是User.class
// descriptor 是前面我们的DependencyDescriptor.class
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
这儿我们需要了解是findAutowireCandidates(beanName, type, descriptor);
方法,具体的内容如下:
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 这儿是查找对应的beanName
// this DefaultListableBeanFactory
// requiredType User.class
// true 查找的时候包含非单例的Bean
// descriptor.isEager() 是否是非延迟加载
// 这儿返回的beanName 应该是两个 一个 user 一个是superUser
// 这儿是有序的,这儿的顺序就是你定义的顺序
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 这儿代码我们不需要看,与我们的主流程没有任何关系,直接跳过
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 直接跳到这个地方
// 这儿遍历两次,将刚刚找出来的beanName,然后找到对应的Class 添加到reslut中去
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 这儿的长度是2,直接返回
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
上面的流程走完了,我们在回到原来的代码,具体的如下:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter
typeConverter) throws BeansException {
// 只有多次嵌套的时候这儿才不会返回null
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 快捷方式这儿也是没有的,返回的是null
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 这儿返回的是user类型
Class<?> type = descriptor.getDependencyType();
// 这儿返回的也是null,后面我们会讲
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 直接跳到这儿执行
// 这儿判断是否要注入的是多个bean,也是null
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 这儿方法中的beanName 等于的是 annotationDependencyInjectionResolutionDemo 也是被注入的beanName
// type 是User.class
// descriptor 是前面我们的DependencyDescriptor.class
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 这个map的长度是2,这个判断是不会进的,继续往下走
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 会走到这儿
if (matchingBeans.size() > 1) {
// 这儿会找到首要的Bean,就是Primary
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
// 这儿找到了superUser
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
// 添加到对应autowiredBeanNames 添加的内容是superUser
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// superUser 直接getBean 这儿直接转成一个Bean对象
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
// 最终返回了
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上面的源码分析,是注入一个简单的,下面我们来分析下注入集合的。将原来的示例代码修改如下:
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
@Autowired // 集合类型的依赖注入
private Map<String, User> users; // user superUser
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.user = " + demo.user);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
前面的代码都是一样的,我们直接看如下的代码:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter
typeConverter) throws BeansException {
// 只有多次嵌套的时候这儿才不会返回null
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 快捷方式这儿也是没有的,返回的是null
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 这儿返回的是user类型
Class<?> type = descriptor.getDependencyType();
// 这儿返回的也是null,后面我们会讲
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 直接跳到这儿执行
// 这儿判断是否要注入的是多个bean,我们先跳到这个方法中看对应的代码
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
这儿直接调用的resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
这个方法,具体的代码如下:
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
// 这儿的获取的类型是map
final Class<?> type = descriptor.getDependencyType();
// 判断不满足 直接跳过
if (descriptor instanceof StreamDependencyDescriptor) {
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
// 判断不满足 直接跳过
else if (type.isArray()) {
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[]) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
Arrays.sort((Object[]) result, comparator);
}
}
return result;
}
// 判断不满足 直接跳过
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
return result;
}
// 直接跳到这个地方
else if (Map.class == type) {
// 获取Map的类型
ResolvableType mapType = descriptor.getResolvableType().asMap();
// 获取 Map的key 的类型 String.class
Class<?> keyType = mapType.resolveGeneric(0);
// 判断不成立 继续
if (String.class != keyType) {
return null;
}
// 获取 Map的value的类型 User.class
Class<?> valueType = mapType.resolveGeneric(1);
// 判断不成立 继续
if (valueType == null) {
return null;
}
// 将这个value的类型调用前面我们讲过的方法 和前面的逻辑是一样的,进行查找,这个时候返回是user superUser
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
// 这儿查找出来了,不会空,继续
if (matchingBeans.isEmpty()) {
return null;
}
// 这儿也不是空,直接将对应beanName添加到autowiredBeanNames 返回
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
由于这儿返回不是null,所以doResolveDependency()
也不会走接下来的逻辑,直接返回,这样就找到了。
还有Optional
、ObjectFactory
,ObjectProvider
,Lazy的情况,我这儿就不讲了,感兴趣的可以去看看。需要注意的是如果是Lazy的话,返回的是代理的对象,只有在使用的时候,才会初始化。
17.@Autowired 注入
@Autowired 注入规则
- 非静态字段
- 非静态方法
- 构造器
@Autowired 注入过程
- 元信息解析
- 依赖查找
- 依赖注入( 字段、 方法)
前面的代码我们主要分析的是依赖的查找的过程,但是@Autowired
注入过程还有两个比较重要的过程,一个是元信息解析,还有一个是依赖的注入。这个时候我们需要通过idea的调用栈来得到这一部分的答案。主要调用的是AutowiredAnnotationBeanPostProcessor#AutowiredFieldElement#inject
的方法,具体的代码如下:
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 需要注入的filed
Field field = (Field) this.member;
Object value;
// 默认是false,直接跳过
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// 创建DependencyDescriptor 依赖描述
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// 设置包含的类 AnnotationDependencyInjectionResolutionDemo.class
desc.setContainingClass(bean.getClass());
// 装配的beanName 后面会进行查找
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 获取类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 依赖的查找,前面讲的
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 这儿是处理缓存,查找出来就缓存起来
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
// 找到了,通过反射的方法创建对应的file,然后set进去。
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
这个时候我们需要通过对应的调用栈继续往上查找,先看到的是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
具体的代码如下:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
我们需要看findAutowiringMetadata(beanName, beanType, null);
元数据的解析。代码的如下:
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 获取的 缓存的key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 从缓存中取值,第一次肯定为空
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
// 再次从缓存中取值,还是为空
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 构建元数据
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 通过递归的查找 @Autowired 的属性,直至查找Object.class
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 查找对应的属性是否有 @Autowired 的注解
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// 这儿我们也可以看出是不支持 static的属性
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断是否是required
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 通过递归的查找 @Autowired 的方法,直至查找Object.class
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
通过上面的分析,元信息解析是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
,依赖查找,依赖注入( 字段、 方法)是org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
18.@Inject 注入
@Inject 注入过程
- 如果 JSR-330 存在于 ClassPath 中, 复用 AutowiredAnnotationBeanPostProcessor 实现
我们可以看下AutowiredAnnotationBeanPostProcessor
,这个类可以处理的注解是@Value、@Autowired、@Inject
,具体的如下:
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
那么是怎么去针对出现多个对应的注解查找呢?findAutowiredAnnotation(AccessibleObject ao)
我们需要看的方法如下:
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
// autowiredAnnotationTypes 是LinkedHashSet是有序的,这儿的插入的属性是Autowired Value Inject
// 所以如果一个字段或者方法上出现多个这个注解优先处理Autowired注解
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
这个时候我们简单的演示一个例子。具体的如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>learn-spring-core</artifactId>
<groupId>org.learn.spring</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dependency-injection</artifactId>
<dependencies>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>ioc-container-overview</artifactId>
<version>${version}</version>
<scope>compile</scope>
</dependency>
<!-- JSR 303 -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
</project>
package org.learn.spring.dependency.injection;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
@Autowired // 集合类型的依赖注入
private Map<String, User> users; // user superUser
@Inject
private User injectUser;
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.injectUser = " + demo.injectUser);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
19.Java通用注解注入原理
CommonAnnotationBeanPostProcessor
- 注入注解
- javax.xml.ws.WebServiceRef
- javax.ejb.EJB
- javax.annotation.Resource
- 生命周期注解
- javax.annotation.PostConstruct
- javax.annotation.PreDestroy
其实CommonAnnotationBeanPostProcessor
的处理和AutowiredAnnotationBeanPostProcessor
的处理是差不多,这儿我们看下不同的地方,具体的如下:
先来看下处理的类型:
static {
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
webServiceRefClass = clazz;
}
catch (ClassNotFoundException ex) {
webServiceRefClass = null;
}
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
ejbRefClass = clazz;
}
catch (ClassNotFoundException ex) {
ejbRefClass = null;
}
// @Resource 注解
resourceAnnotationTypes.add(Resource.class);
// @WebServiceRef 注解
if (webServiceRefClass != null) {
resourceAnnotationTypes.add(webServiceRefClass);
}
// @EJB 注解
if (ejbRefClass != null) {
resourceAnnotationTypes.add(ejbRefClass);
}
}
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
// @PostConstruct注解
setInitAnnotationType(PostConstruct.class);
// @PreDestroy 注解
setDestroyAnnotationType(PreDestroy.class);
// @WebServiceContext 注解
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
然后就是元数据的解析,具体的如下:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 调用父类的postProcessMergedBeanDefinition的方法,主要的是处理生命周期的元数据
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
我们先来看看生命周期的元数据的处理,具体的如下:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
上面的代码熟悉嘛?和前面的AutowiredAnnotationBeanPostProcessor
几乎是一样的,这儿我不做过多的赘述了。然后处理完了生命周期的函数,我们再来看看需要注入的数据的处理。具体的如下:
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
流程也是一样的,这儿也不做过多的赘述,我们再来看依赖查找和依赖的注入的流程,具体的如下:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
流程是一样的,这儿也不做过多的赘述。我们需要了解的是生命周期的函数的处理。前面的已经生成对应的LifecycleMetadata
那么在什么地方调用呢?
可以看到InitDestroyAnnotationBeanPostProcessor
中的调用。具体的代码如下:
初始化的方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
销毁的方法
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeDestroyMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
}
else {
logger.warn(msg + ": " + ex.getTargetException());
}
}
catch (Throwable ex) {
logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
}
}
20.自定义依赖注入注解
基于 AutowiredAnnotationBeanPostProcessor
实现
自定义实现
-
生命周期处理
-
InstantiationAwareBeanPostProcessor
-
MergedBeanDefinitionPostProcessor
-
-
元数据
InjectedElement
InjectionMetadata
第一种方式可以通过元注解的方式,具体的如下:
package org.learn.spring.dependency.injection.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 自定义注解
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface MyAutowired {
boolean required() default true;
}
package org.learn.spring.dependency.injection;
import org.learn.spring.dependency.injection.annotation.MyAutowired;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
@Autowired // 集合类型的依赖注入
private Map<String, User> users; // user superUser
@MyAutowired
private User injectUser;
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.injectUser = " + demo.injectUser);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
通过自定义注解的方式,具体的代码如下:
package org.learn.spring.dependency.injection;
import org.learn.spring.dependency.injection.annotation.InjectUser;
import org.learn.spring.dependency.injection.annotation.MyAutowired;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
@Autowired // 集合类型的依赖注入
private Map<String, User> users; // user superUser
@Inject
private User injectUser;
@InjectUser
private User myInjectUser;
// 标记成static字段的话,会提前初始化
@Bean(value = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// @Autowired + @Inject + 新的注解@InjectUser处理
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectUser.class));
autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
return autowiredAnnotationBeanPostProcessor;
}
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.user = " + demo.user);
System.out.println("demo.injectUser = " + demo.injectUser);
System.out.println("demo.myInjectUser = " + demo.myInjectUser);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
但是上面的代码如果Inject.class
如果不存在时候就会报错,不安全,那么我们可以改成如下的:
package org.learn.spring.dependency.injection;
import org.learn.spring.dependency.injection.annotation.InjectUser;
import org.learn.spring.dependency.injection.annotation.MyAutowired;
import org.learn.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;
// 注解实现延迟依赖注入处理过程
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依赖查找(处理)
private User user; // DependencyDescriptor ->
// 必须(required = true)
// (eager = true) 实时注入
// 通过类型(User.class)
// 字段名称("user")
// 是否是首要的(primary = true)
@Autowired // 集合类型的依赖注入
private Map<String, User> users; // user superUser
@Inject
private User injectUser;
@InjectUser
private User myInjectUser;
// 标记成static字段的话,会提前初始化
/*@Bean(value = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// @Autowired + @Inject + 新的注解@InjectUser处理
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectUser.class));
autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
return autowiredAnnotationBeanPostProcessor;
}*/
// 新老注解同时存在
@Bean
@Order(Ordered.LOWEST_PRECEDENCE - 3)
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectUser.class);
return autowiredAnnotationBeanPostProcessor;
}
public static void main(String[] args) {
// 创建BeanFactory的容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册Configuration Class 配置类 -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加载XML资源,解析并生成BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找 LazyAnnotationDependencyInjectionDemo Bean
AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);
// 期待输出superUser Bean
System.out.println("demo.user = " + demo.user);
System.out.println("demo.injectUser = " + demo.injectUser);
System.out.println("demo.myInjectUser = " + demo.myInjectUser);
// 显示的关闭spring应用上下文
applicationContext.close();
}
}
21.面试题
有多少种依赖注入的方式?
- 构造器注入
- Setter 注入
- 字段注入
- 方法注入
- 接口回调注入
你偏好构造器注入还是 Setter 注入?
两种依赖注入的方式均可使用, 如果是必须依赖的话, 那么推荐使用构造器注入, Setter 注入用于可选依赖。