Spring的依赖注入冲突

  学习到Spring的自动依赖注入时,突然想到<Bean>的autowire="constructor"时,如果有多个构造器满足注入的条件时会发生什么。我在CSDN一篇关于自动注入的博客找到了相关的解释Spring自动注入详解   (转载,不知道原创出处)。但进而考虑到byName和byType会不会也有冲突的问题呢?

 

一、constructor 自动依赖注入冲突

  当有多个构造器可以注入时:

  1. 先按修饰符排序,public优先
  2. 再按参数个数排序,参数多的优先
  3. 构造器参数相同,但参数的顺序不同时,写在前面的优先               参考:Spring常用的三种注入方式
public class User {
    private int id;
    private int age;
    private String name;
    private Person person;

    public User() {
    }

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public User(Person person) {
        System.out.println("constructor_1: person");
        this.id = person.getId();
        this.age = person.getAge();
        this.name = person.getName();
        this.person = person;
    }

    public User(Person person, int id) {
        System.out.println("constructor_2: person id");
        this.id = id;
        this.age = person.getAge();
        this.name = person.getName();
        this.person = person;
    }
    //各参数的getter和setter方法,重写的toString方法 
}
    <bean id="person" class="pojo.Person" p:id="2" p:age="22" p:name="person"/>
    <bean id="user1" name="user" class="pojo.User" autowire="constructor"/>
    <bean id="user2" name="user" class="pojo.User" autowire="constructor" c:id="5"/>
public class Main {
    public static void main(String[] args) {
        AbstractApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        User user1 =(User) app.getBean("user1");
        User user2 =(User) app.getBean("user2");
        System.out.println(user1);
        System.out.println(user2);
    }
}

 

运行结果:

  

 


二、byName 和 byType 重载set方法冲突

  ps:没有找到相关的资料,仅为个人的尝试和思考。

如果出现了set方法的重载,Spring如何选择set方法。

  • setAge(int age){};
  • setAge(Integer age){};

 

下面分类讨论通过set的自动注入的模式:

1、byName :根据BeanID去匹配set的属性名

  如果重载setAge方法冲突,则需要有多个相同ID的Bean,故冲突转移到了BeanID的冲突上。

 

2、byType :根据set的参数类型去匹配Bean。

  方法的重载需要参数列表不同 

  • 单参数set方法:

    下面是Human类和Person类,两个类基本相同,并提供了互相转换的toPerson()和toHuman方法

package pojo;

public class Person {
    private int id;
    private int age;
    private String name;

    public Person(){
    }
    public Person(int id, int age, String name){
        this.id = id;
        this.age = age;
        this.name = name;
    }
    public Human toHuman(){
        Human human = new Human();
        human.setId(this.id);
        human.setAge(this.age);
        human.setName(this.name);
        return human;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return id + " " + age + " " + name;
    }
}
Person.class
public class Human {
    private int id;
    private int age;
    private String name;

    public Human(){
    }
    public Human(int id, int age, String name){
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public Person toPerson(){
        Person pserson = new Person();
        pserson.setId(this.id);
        pserson.setAge(this.age);
        pserson.setName(this.name);
        return pserson;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return id + " " + age + " " + name;
    }
}
Human.class

    User类,可以通过set方法接收Human和Person进行初始化。重载了setHuman()和setPerson()

public class User {
    private int id;
    private int age;
    private String name;
    private Person person;
    private Human human;

    public User() {
    }

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public Person getPerson() {
        return person;
    }

    public Human getHuman() {
        return human;
    }

    public void setHuman(Human human) {
        System.out.println("名参相同:setHuman human");
        this.human = human;
        this.person = human.toPerson();
        this.id = human.getId();
        this.age = human.getAge();
        this.name = human.getName();
    }

    public void setHuman(Person person) {
        System.out.println("名参不同:setHuman person");
        this.person = person;
        this.human = person.toHuman();
        this.id = person.getId();
        this.age = person.getAge();
        this.name = person.getName();

    }

    public void setPerson(Person person) {
        System.out.println("名参相同:setPerson person");
        this.person = person;
        this.human = person.toHuman();
        this.id = person.getId();
        this.age = person.getAge();
        this.name = person.getName();
    }

    public void setPerson(Human human) {
        System.out.println("名参不同:setPerson human");
        this.human = human;
        this.person = human.toPerson();
        this.id = human.getId();
        this.age = human.getAge();
        this.name = human.getName();
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return id + " " + age + " " + name;
    }
}

    没有发现直观的规律,最终的值取决于Spring执行set注入的顺序

    运行结果:

      

 

 

  • 多参数set方法:

   多参数的set方法不符合标准JavaBean的定义

 


 

三、同时有构造注入和set注入的冲突

  先进行构造注入,再进行set注入。毕竟得先用构造器创建对象,才能调用它的实例方法。

  参考文章:set注入和构造注入顺序

   <bean id="person" class="pojo.Person" c:id="2" c:age="22" c:name="构造注入">
        <property name="name" value="set注入"/>
   </bean>

  运行结果:  

    

 

 

如果有错误或需要补充的内容,请评论告诉我,谢谢!

posted @ 2022-10-05 19:51  侍墨  阅读(282)  评论(0)    收藏  举报