在上一篇的文章中,我们着重讲解了Spring内部的依赖查找这玩意,这一次着重介绍关于spring的依赖注入模块。
关于依赖注入这块,本篇重点介绍实战方面的内容,实战案例的代码有些多,希望在分享结束后能对各位读者对Spring的依赖注入有个更加清晰的认识。
依赖注入的模式
我们通常在使用Spring的时候主要是用注解或者xml的方式进行注入,如果做过基于Spring容器的二次开发的朋友应该还清楚直接基于Spring的API方式进行依赖注入。
依赖注入的模式主要可以分为两个大类别:
- 手动模式的注入
- 自动模式的注入
手动模式
- XML模式的资源配置
- Java注解的配置方式
- API配置方式(一般如果没有对于容器进行开发,使用会比较少)
自动模式
Autowiring 的自动绑定模式
了解清楚了这两个大的模式之后,我们再来继续细分,依赖注入的几种常用类型。
Setter注入
XML模式
代码案例:
PersonBean对象(后边会多次用到这个对象)
package org.idea.spring.dependency.inject.setter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.idea.spring.ioc.bean.Person;
/**
* 自动绑定
*
* @Author linhao
* @Date created in 10:44 下午 2021/4/21
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PersonHolder {
private Person person;
}
Person代码
package org.idea.spring.ioc.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author idea
* @Date created in 10:45 下午 2020/4/30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
Integer id;
String name;
}
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">
<bean id="malePerson" class="org.idea.spring.ioc.bean.Person" >
<property name="id" value="1"></property>
<property name="name" value="idea"></property>
</bean>
<bean class="org.idea.spring.dependency.inject.setter.PersonHolder">
<property name="person" ref="malePerson"></property>
</bean>
</beans>
PersonHolder内部引用了一个Person对象。
Spring容器的代码
package org.idea.spring.dependency.inject.setter;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* 基于xml的依赖注入方式案例
*
* @Author linhao
* @Date created in 8:29 上午 2021/4/20
*/
public class InDependencyInjectDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String xmlPath = "classpath:/META-INF/independency-inject.xml";
xmlBeanDefinitionReader.loadBeanDefinitions(xmlPath);
PersonHolder personHolder = beanFactory.getBean(PersonHolder.class);
System.out.println(personHolder);
}
}
注解模式
Spring内部代码块
package org.idea.spring.dependency.inject.setter;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Map;
/**
* 基于注解的依赖注入
*
* @Author linhao
* @Date created in 10:53 下午 2021/4/21
*/
public class AnnotationDependencyInjectDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AnnotationConfigApplicationContext.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/bean-ioc.xml");
applicationContext.register(PersonHolder.class);
applicationContext.refresh();
Map<String,Person> personMap= applicationContext.getBeansOfType(Person.class);
for (String key : personMap.keySet()) {
System.out.println(key);
}
PersonHolder personHolder = applicationContext.getBean(PersonHolder.class);
System.out.println(personHolder);
applicationContext.close();
}
/**
* 这里需要先对person的bean进行初始化才能注入
*
* @param
* @return
*/
@Bean
public PersonHolder personHolder(Person person){
return new PersonHolder(person);
}
}
API模式
基于Spring容器的内部api进行其实也可以实现依赖的注入:
package org.idea.spring.dependency.inject.setter;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* 通过api的方式进行注入实现
*
* @Author linhao
* @Date created in 11:11 下午 2021/4/21
*/
public class ApiDependencyInjectDemo {
@Bean
public Person myPerson(){
return new Person(1,"idea");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(ApiDependencyInjectDemo.class);
BeanDefinition personBeanDefinition = createUserBeanDefinition();
applicationContext.registerBeanDefinition("personHolder",personBeanDefinition);
applicationContext.refresh();
PersonHolder personHolder = applicationContext.getBean(PersonHolder.class);
System.out.println(personHolder.getPerson());
applicationContext.close();
}
private static BeanDefinition createUserBeanDefinition() {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(PersonHolder.class);
//注意这里的add方法有多种类型,需要注意下细节点
beanDefinitionBuilder.addPropertyReference("person","myPerson");
return beanDefinitionBuilder.getBeanDefinition();
}
}
上边的三种注入方式主要是基于Bean对象内部的setter方法和getter方法作为基础进行注入引用的,除此之外,其实还可以基于对象的构造函数来实现字段的引入。
构造器注入
XML模式
首先是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">
<bean id="femalePerson" class="org.idea.spring.ioc.bean.FemalePerson"></bean>
<bean class="org.idea.spring.dependency.inject.setter.PersonHolder">
<constructor-arg name="person" ref="femalePerson"></constructor-arg>
</bean>
</beans>
Spring容器的相关代码:
package org.idea.spring.dependency.inject.constructor;
import org.idea.spring.dependency.inject.setter.PersonHolder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* @Author linhao
* @Date created in 10:21 下午 2021/4/22
*/
public class XmlDependencyInjectDemo {
public static void main(String[] args) {
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/independency-constructor-inject.xml");
PersonHolder personHolder = defaultListableBeanFactory.getBean(PersonHolder.class);
System.out.println(personHolder.getPerson());
}
}
注解模式
基于注解的实现方式比较简单,这里我也直接贴出代码了:
package org.idea.spring.dependency.inject.constructor;
import org.idea.spring.dependency.inject.setter.PersonHolder;
import org.idea.spring.ioc.bean.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* @Author linhao
* @Date created in 10:25 下午 2021/4/22
*/
public class AnnotationDependencyInjectDemo {
@Bean
public Person femalePerson(){
return new Person(1,"idea2");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(AnnotationDependencyInjectDemo.class);
annotationConfigApplicationContext.refresh();
PersonHolder personHolder = annotationConfigApplicationContext.getBean(PersonHolder.class);
System.out.println(personHolder);
annotationConfigApplicationContext.close();
}
/**
* 自动会进行bean的注入
*
* @param femalePerson
* @return
*/
@Bean
public PersonHolder personHolder(Person femalePerson){
return new PersonHolder(femalePerson);
}
}
代码中的personHolder bean在进行初始化的时候会自动通过名称匹配给femalePerson进行依赖注入。
Api模式
如果有遇到过对Spring容器做改造的需求,可能就会需要了解到类似下边的这种代码:
package org.idea.spring.dependency.inject.constructor;
import org.idea.spring.dependency.inject.setter.PersonHolder;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* @Author linhao
* @Date created in 10:28 下午 2021/4/22
*/
public class ApiDependencyInjectDemo {
@Bean
public Person myPerson(){
return new Person(1,"idea");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(ApiDependencyInjectDemo.class);
BeanDefinition personBeanDefinition = createUserBeanDefinition();
applicationContext.registerBeanDefinition("personHolder",personBeanDefinition);
applicationContext.refresh();
PersonHolder personHolder = applicationContext.getBean(PersonHolder.class);
System.out.println(personHolder.getPerson());
applicationContext.close();
}
private static BeanDefinition createUserBeanDefinition() {
//spring官方比较推荐的一种注入方式
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(PersonHolder.class);
//注意这里的add方法有多种类型,需要注意下细节点
beanDefinitionBuilder.addConstructorArgReference("myPerson");
return beanDefinitionBuilder.getBeanDefinition();
}
}
其实不管是注解还是xml,在底层都是基于使用BeanDefinition的构建,然后再使用Spring容器注册这个BeanDefinition来实现依赖注入的。
字段注入
字段注入的模式就是我们比较常在工作中使用的案例了,常见的注入注解有:
@Autowired
@Resource
例如下边的代码:
package org.idea.spring.dependency.inject.field;
import org.idea.spring.dependency.inject.setter.PersonHolder;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.annotation.Resource;
/**
* @Author linhao
* @Date created in 10:48 下午 2021/4/22
*/
public class AnnotationDependencyInjectDemo {
@Autowired
private PersonHolder personHolder2;
@Resource
private PersonHolder personHolder;
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AnnotationDependencyInjectDemo.class);
applicationContext.refresh();
AnnotationDependencyInjectDemo annotationDependencyInjectDemo = applicationContext.getBean(AnnotationDependencyInjectDemo.class);
System.out.println(annotationDependencyInjectDemo.personHolder);
System.out.println(annotationDependencyInjectDemo.personHolder2);
//这里面的两个bean都是同一个,因为bean的作用域是一致相同的
System.out.println(annotationDependencyInjectDemo.personHolder == annotationDependencyInjectDemo.personHolder2);
applicationContext.close();
}
@Bean
public PersonHolder personHolder(){
return new PersonHolder(new Person(1,"idea"));
}
}
这里面容易让人有所疑惑的点:
在同一个类里面声明了一个Bean,然后在该Bean中直接引用是否会报错?
经过实践后发现,并不会有影响。
代码案例中的personHolder2和personHolder是否是同一个对象?
如果我们的PersonHolder是单例模式的话,那么就是同一个对象。
方法注入
所谓的方法注入,我个人的理解就是对方法的入参也支持依赖注入的功能。例如下边这段代码案例:
package org.idea.spring.dependency.inject.method;
import org.idea.spring.dependency.inject.setter.PersonHolder;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import javax.annotation.Resource;
/**
* spring内部的方法注入实现
* @Author linhao
* @Date created in 10:24 上午 2021/4/23
*/
public class MethodInjectDemo {
private PersonHolder personHolder;
private PersonHolder personHolder_resource;
@Resource
public void initPersonHolderResource(PersonHolder personHolder){
this.personHolder_resource = personHolder;
}
@Autowired
public void initPersonHolder(PersonHolder personHolder){
this.personHolder = personHolder;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(MethodInjectDemo.class);
annotationConfigApplicationContext.refresh();
MethodInjectDemo methodInjectDemo = annotationConfigApplicationContext.getBean(MethodInjectDemo.class);
System.out.println(methodInjectDemo.personHolder);
System.out.println(methodInjectDemo.personHolder_resource);
//修改bean的作用域则可以判断为不相同
System.out.println(methodInjectDemo.personHolder == methodInjectDemo.personHolder_resource);
// annotationConfigApplicationContext
annotationConfigApplicationContext.close();
}
@Bean
@Scope(value = "prototype")
public Person femalePerson(){
return new Person(1,"female");
}
@Bean
@Scope(value = "prototype")
public PersonHolder personHolder(Person person){
return new PersonHolder(person);
}
}
这里你会发现我将PersonHolder的@Scope属性做了调整,所以@AutoWired注解和@Resource注解引入的对象就不会是同一个对象。
回调注入
在Spring容器中一般以Aware作为结尾命名的对象都是能够接收一些特殊的回调通知功能,因此在Spring回调相关对象的时候可以注入一些依赖,从而实现基于回调的依赖注入。
代码案例如下:
package org.idea.spring.dependency.inject.aware;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* @Author linhao
* @Date created in 11:11 上午 2021/4/23
*/
public class AwareInjectDemo implements BeanFactoryAware, ApplicationContextAware {
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(AwareInjectDemo.class);
annotationConfigApplicationContext.refresh();
AwareInjectDemo awareInjectDemo = annotationConfigApplicationContext.getBean(AwareInjectDemo.class);
Person person = (Person) awareInjectDemo.beanFactory.getBean("person");
System.out.println(annotationConfigApplicationContext.getBeanFactory() == awareInjectDemo.beanFactory);
//当前的上下文和回调注入的上下文是同一个对象
System.out.println(awareInjectDemo.applicationContext == annotationConfigApplicationContext);
System.out.println(person);
annotationConfigApplicationContext.close();
}
@Bean
public Person person(){
return new Person(1,"idea");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
关于Spring内部的依赖注入类型大致整理了一下如下所示:
而在实际使用过程中,我们还有可能会遇到一些复杂参数的注入,这里我也做了一些相关的技术整理。
特殊格式参数的注入
枚举字段注入
基于xml的方式使用枚举字段的依赖注入:
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">
<bean id="user" class="org.idea.spring.dependency.inject.type.User">
<property name="id" value="1"></property>
<property name="name" value="idea"></property>
<property name="age" value="11"></property>
<property name="cities" value="WUHAN,BEIJING,SHANGHAI" ></property>
</bean>
</beans>
代码案例:
package org.idea.spring.dependency.inject.type;
import javax.annotation.PostConstruct;
import java.util.Arrays;
public class User {
private int id;
private String name;
private Integer age;
private City[] cities;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public City[] getCities() {
return cities;
}
public void setCities(City[] cities) {
this.cities = cities;
}
@PostConstruct
public void init(){
System.out.println("this is init");
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", cities=" + Arrays.toString(cities) +
'}';
}
}
枚举对象
package org.idea.spring.dependency.inject.type;
public enum City{
WUHAN,
BEIJING,
SHANGHAI;
City() {
}
}
注入代码案例
package org.idea.spring.dependency.inject.type;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* 关于枚举的注入
*
* @Author linhao
* @Date created in 12:28 下午 2021/4/23
*/
public class EnumInjectDemo {
public static void main(String[] args) {
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
String xmlPath = "classpath:/META-INF/type-independency-inject.xml";
xmlBeanDefinitionReader.loadBeanDefinitions(xmlPath);
User user = defaultListableBeanFactory.getBean(User.class);
System.out.println(user);
}
}
List集合的注入
代码案例:
package org.idea.spring.dependency.inject.type;
import java.util.List;
/**
* @Author linhao
* @Date created in 3:51 下午 2021/4/23
*/
public class ListObject {
private Integer id;
private String username;
private List<String> list;
public ListObject() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public ListObject(Integer id, String username, List<String> list) {
this.id = id;
this.username = username;
this.list = list;
}
}
针对list类型参数的依赖注入
package org.idea.spring.dependency.inject.type;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
/**
* @Author linhao
* @Date created in 3:53 下午 2021/4/23
*/
public class ListObjectInjectDemo {
public static void main(String[] args) {
String xmlPath = "classpath:/META-INF/type-list-independency-inject.xml";
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions(xmlPath);
ListObject listObject = defaultListableBeanFactory.getBean(ListObject.class);
System.out.println(listObject);
}
}
资源文件的注入
关于资源这块的注入我们需要先引入一些properties文件作为基础
properties内容
user.passowrd=10001
user.email=idea@qq.com
对应的Bean对象中使用org.springframework.core.io.Resource作为引用。
public class ResourceObject {
private Long id;
private String name;
private Integer age;
private Resource configFileResource;
//gett sett 省略
}
而对应的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">
<bean id="user" class="org.idea.spring.dependency.inject.type.ResourceObject">
<property name="id" value="1"></property>
<property name="name" value="idea"></property>
<property name="age" value="11"></property>
<property name="configFileResource" value="classpath:/META-INF/user-config.properties" ></property>
</bean>
</beans>
Qualifier注解的注入
这里介绍下Qualifier这款注解。
我们常用的@Autowired注解是根据类型进行自动装配的,如果Spring的上下文中按照类型匹配出现了多个重复的bean的时候,就会抛出异常。例如下边这段代码中,存在user1,user2两个Bean,但是他们的Bean类型都是User,因此在进行自动装配的时候就会抛出异常,此时如果多加入一个@Qualifier注解,就能够同时支持@Autowired区分Bean名称来进行注入的效果了。
但是我个人习惯一般是比较推崇使用@Resource方式的注入,而且官方也并不是特别推崇@Autowired 注解。
package org.idea.spring.dependency.inject.type;
import org.idea.spring.ioc.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import javax.annotation.Resource;
/**
* @Author linhao
* @Date created in 4:02 下午 2021/4/23
*/
public class QualifierInjectDemo {
@Autowired
// @Resource
//按照user2的名字进行字段注入,这里会注入user2的对象实例
//如果加入了@Resource注解的话,就会注入user1对象,而且优先级比user2要高
@Qualifier("user2")
private User user1;
// @Autowired
@Resource
private User user2;
@Autowired
@Qualifier //这里带有@Qualifier注解之后,会自动注入person() 这个bean
private Person person;
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(QualifierInjectDemo.class);
applicationContext.refresh();
QualifierInjectDemo beanDemo = applicationContext.getBean(QualifierInjectDemo.class);
System.out.println("user1:" + beanDemo.user1);
System.out.println("user2:" + beanDemo.user2) ;
System.out.println("普通:" + beanDemo.user1);
System.out.println("person 分组:"+beanDemo.person);
applicationContext.close();
}
@Bean
@Qualifier
public Person person(){
return new Person(1,"idea");
}
@Bean
public Person femalePerson(){
return new Person(2,"idea2");
}
@Bean
public User user1(){
return createUser("user1");
}
@Bean
public User user2(){
return createUser("user2");
}
private static User createUser(String name) {
User user = new User();
user.setName(name);
return user;
}
}
总结思考
本篇文章主要还是以实践为主,因为我个人觉得在实际工作中,用得最多方式也是@Resource,
@Autowired这两种基于字段的注入方式,对于Spring容器有过二次开发的朋友可能会对Api的注入方式了解颇深。
在通过上述的种种实践案例分析之后,再回过头来进行思考。
依赖注入和依赖查找的比对
相比于主动查找来说,依赖注入总是能够一步到位地将所需要的bean给注入到容器里面,从而不需要后边再做主动查找,更加简单方便。依赖查找中肯定是要使用相应的api接口去主动查询,这对于业务代码是具有一定的侵害性,所以两种方案的选择需要进过自己去深入琢磨。
Setter注入和构造器注入有什么差别
对比两种方式来说,我个人认为都有好坏
1.首先构造器注入有着很明显的先后顺序限制,它和setter注入不同,setter注入的时候通常是由调用方来限制先后顺序的,没法像构造器一样有序地控制注入顺序。
2.构造器注入的方式来说,如果一个类里面需要注入的bean过多的时候,使用构造器注入反而写起来代码会很臃肿,比较难以维护。
3.sett注入的时候,bean可能会有新的变化,也就是说它要比构造器注入更加灵活,动态化控制注入的bean信息。
4.如果某个引入的bean需要在容器启动的时候就被初始化注入,那么使用构造器注入的方式可能更加适合。
5.对于父子继承的对象来说,使用bean的setter注入可以同时影响到子类的注入。
6.构造器注入的方式通常对于注入的bean都是具有统一的状态管理。而且java里面也是推荐一旦对象生成了,后边就不做过多的修改。
Spring内部的bean注入来源有哪些
1.自定义的bean
2.容器内初始化构建好的bean(例如说我们的enviorment对象)
3.容器内建的依赖对象 (例如说我们的beanfactory,无法通过getbean来获取)