深入挖掘Spring系列 -- 依赖注入专题

在上一篇的文章中,我们着重讲解了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来获取)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值