第六章:Spring IoC 注入
依赖注入的模式和类型
模式
手动模式 - 配置或者编程的方式,提前安排注入规则
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
自动模式 - 实现方提供依赖自动关联的方式,按照內建的注入规则
自动绑定(Autowiring)
自动绑定(Autowiring)模式
自动绑定(Autowiring)限制和不足
依赖注入方式
Setter 方法依赖注入
UserHolder注入User
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
| public class UserHolder {
private User user;
public UserHolder() { }
public UserHolder(User user) { this.user = user; }
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
@Override public String toString() { return "UserHolder{" + "user=" + user + '}'; } }
|
手动模式
XML 资源配置元信息
1 2 3 4
| <bean class="com.cruise.thinking.in.spring.dependency.injection.holder.UserHolder"> <property name="user" ref="superUser"/> </bean>
|
Java 注解配置元信息
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
| public class AnnotationDependencySetterInjectionDemo {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AnnotationDependencySetterInjectionDemo.class);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh();
UserHolder userHolder = context.getBean(UserHolder.class);
System.out.println(userHolder);
context.close();
}
@Bean public UserHolder userHolder(User user) { UserHolder userHolder = new UserHolder(); userHolder.setUser(user); return userHolder; } }
|
API 配置元信息
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
| public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.registerBeanDefinition("userHolder", createBeanDefinition()); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh(); UserHolder userHolder = context.getBean(UserHolder.class); System.out.println(userHolder); context.close(); }
private static BeanDefinition createBeanDefinition() { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class); beanDefinitionBuilder.addPropertyReference("user", "superUser"); return beanDefinitionBuilder.getBeanDefinition(); }
|
自动模式
byName
当SpringIOC中存在user名称的对象时,setter注入
1
| <bean class="com.cruise.thinking.in.spring.dependency.injection.holder.UserHolder" autowire="byName"/>
|
byType
将上面的byName改成byType即可
构造器依赖注入
手动模式
XML 资源配置元信息
1 2 3 4 5 6
| <!-- xml 手动 constructor 注入 --> <bean class="com.cruise.thinking.in.spring.dependency.injection.holder.UserHolder"> <!-- 使用name或者index都可以 --> <!--<constructor-arg name="user" ref="superUser"/>--> <constructor-arg index="0" ref="superUser"/> </bean>
|
Java 注解配置元信息
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
| public class AnnotationDependencyConstructorInjectionDemo {
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AnnotationDependencyConstructorInjectionDemo.class);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh();
UserHolder userHolder = context.getBean(UserHolder.class);
System.out.println(userHolder);
context.close();
}
@Bean public UserHolder userHolder(User user) { return new UserHolder(user); } }
|
API 配置元信息
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
| public class ApiDependencyConstructorInjectionDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBeanDefinition("userHolder", createBeanDefinition());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh();
UserHolder userHolder = context.getBean(UserHolder.class);
System.out.println(userHolder);
context.close();
}
private static BeanDefinition createBeanDefinition() { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
beanDefinitionBuilder.addConstructorArgReference("superUser");
return beanDefinitionBuilder.getBeanDefinition(); } }
|
自动模式
constructor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class AutowiringDependencyConstructorInjectionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:/META-INF/autowiring-dependency-injection-constructor.xml");
UserHolder bean = beanFactory.getBean(UserHolder.class);
System.out.println(bean);
} }
|
1 2 3 4 5 6 7 8 9 10 11 12
| <?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="com.cruise.thinking.in.spring.dependency.injection.holder.UserHolder" autowire="constructor"/>
</beans>
|
字段注入
手动模式
Java 注解配置元信息
@Autowired
会自动忽略static属性
@Resource
@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 46
| public class AnnotationDependencyFieldInjectionDemo {
@Autowired private UserHolder userHolder;
@Resource private UserHolder userHolder2;
@Inject private UserHolder userHolder3;
@Autowired private static UserHolder userHolder4;
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AnnotationDependencyFieldInjectionDemo.class);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh();
AnnotationDependencyFieldInjectionDemo bean = context.getBean(AnnotationDependencyFieldInjectionDemo.class);
System.out.println(bean.userHolder); System.out.println(bean.userHolder2); System.out.println(bean.userHolder3); System.out.println(bean.userHolder4); System.out.println(bean.userHolder == bean.userHolder2); System.out.println(bean.userHolder == bean.userHolder3);
context.close(); }
@Bean public UserHolder userHolder(User user) { return new UserHolder(user); } }
|
方法注入
手动模式
Java 注解配置元信息
@Autowired
@Resource
@Inject(可选)
@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 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
| public class AnnotationDependencyMethodInjectionDemo {
private UserHolder userHolder; private UserHolder userHolder2; private UserHolder userHolder3;
@Autowired public void init(UserHolder userHolder) { this.userHolder = userHolder; }
@Resource public void init2(UserHolder userHolder2) { this.userHolder2 = userHolder2; }
@Inject public void init3(UserHolder userHolder3) { this.userHolder3 = userHolder3; }
@Bean public UserHolder userHolder(User user) { return new UserHolder(user); }
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AnnotationDependencyMethodInjectionDemo.class);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context); reader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");
context.refresh();
AnnotationDependencyMethodInjectionDemo bean = context.getBean(AnnotationDependencyMethodInjectionDemo.class);
System.out.println(bean.userHolder); System.out.println(bean.userHolder2); System.out.println(bean.userHolder3); System.out.println(bean.userHolder == bean.userHolder2); System.out.println(bean.userHolder == bean.userHolder3);
context.close(); }
}
|
回调注入(Aware接口)


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
| public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareInterfaceDependencyInjectionDemo.class);
AwareInterfaceDependencyInjectionDemo bean = context.getBean(AwareInterfaceDependencyInjectionDemo.class);
System.out.println(bean.applicationContext == context); System.out.println(bean.beanFactory == context.getBeanFactory());
context.close(); }
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
|
依赖注入类型选择

基础类型注入

CityHolder, 需要注入Object , Resource、Optional
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
| public class CityHolder {
private City city;
private Resource cityResource;
private Optional<String> desc;
public City getCity() { return city; }
public void setCity(City city) { this.city = city; }
public Resource getCityResource() { return cityResource; }
public void setCityResource(Resource cityResource) { this.cityResource = cityResource; }
public Optional<String> getDesc() { return desc; }
public void setDesc(Optional<String> desc) { this.desc = desc; }
@Override public String toString() { return "CityHolder{" + "city=" + city + ", cityResource=" + cityResource + ", desc=" + desc + '}'; } }
|
Xml的配置信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <bean id="cityHolder" class="com.cruise.thinking.in.spring.dependency.injection.holder.CityHolder"> <property name="city" value="BEIJING"/> <property name="cityResource" value="classpath:/META-INF/city.properties"/> <property name="desc" ref="optional"/> </bean>
<bean id="optional" class="java.util.Optional"> <constructor-arg name="value" value="北京"/> </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
| public class MultiCityHolder {
private City[] cities;
private List<City> cityList;
public City[] getCities() { return cities; }
public void setCities(City[] cities) { this.cities = cities; }
public List<City> getCityList() { return cityList; }
public void setCityList(List<City> cityList) { this.cityList = cityList; }
@Override public String toString() { return "MultiCityHolder{" + "cities=" + Arrays.toString(cities) + ", cityList=" + cityList + '}'; } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="multiCityHolder" class="com.cruise.thinking.in.spring.dependency.injection.holder.MultiCityHolder"> <property name="cities" value="BEIJING,HANGZHOU"/> <property name="cityList"> <list> <value>BEIJING</value> <value>SHANGHAI</value> </list> </property> </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 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 93 94
| public class QualifierDependencyInjectionDemo {
@Autowired private User user;
@Autowired @Qualifier("user") private User namedUser;
@Autowired private List<User> allUsers;
@Autowired @Qualifier private List<User> qualifierUsers;
@Autowired @UserGroup private List<User> groupUsers;
@Bean public User user() { User user = new User(); user.setId(1L); return user; }
@Bean @Primary public SuperUser superUser() { SuperUser superUser = new SuperUser(); superUser.setId(2L); return superUser; }
@Bean @Qualifier public User user1() { User user = new User(); user.setId(3L); return user; }
@Bean @Qualifier public User user2() { User user = new User(); user.setId(4L); return user; }
@Bean @UserGroup public User user3() { User user = new User(); user.setId(5L); return user; }
@Bean @UserGroup public User user4() { User user = new User(); user.setId(6L); return user; }
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(QualifierDependencyInjectionDemo.class);
QualifierDependencyInjectionDemo bean = context.getBean(QualifierDependencyInjectionDemo.class);
System.out.println("bean.user" + bean.user); System.out.println("bean.namedUser" + bean.namedUser); System.out.println("bean.allUsers" + bean.allUsers); System.out.println("bean.qualifierUsers" + bean.qualifierUsers); System.out.println("bean.groupUsers" + bean.groupUsers); context.close(); } }
|
1 2 3 4 5
| bean.usersuperUser{address='null'} User{id=2, name='null'} bean.namedUserUser{id=1, name='null'} bean.allUsers[User{id=1, name='null'}, superUser{address='null'} User{id=2, name='null'}, User{id=3, name='null'}, User{id=4, name='null'}, User{id=5, name='null'}, User{id=6, name='null'}] bean.qualifierUsers[User{id=3, name='null'}, User{id=4, name='null'}, User{id=5, name='null'}, User{id=6, name='null'}] bean.groupUsers[User{id=5, name='null'}, User{id=6, name='null'}]
|
UserGroup 上面有@Qualifier注解
1 2 3 4 5 6 7 8
| @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Qualifier public @interface UserGroup { }
|
延迟依赖注入

依赖处理过程

@Autowired 注入原理
JSR-330 @Inject 注入原理
Java通用注解注入原理
自定义依赖注入注解
面试题精选