主頁 >  其他 > Spring系列第八講 自動注入(autowire)詳解,高手在于堅持!

Spring系列第八講 自動注入(autowire)詳解,高手在于堅持!

2020-10-21 06:50:40 其他

Spring系列第八講

  • 手動注入的不足
  • Class.isAssignableFrom方法
    • 用法
    • 案例
  • 自動注入
  • 按照名稱進行注入(byName)
    • 用法
    • 案例
    • 優缺點
  • 按照型別進行自動注入
    • 用法
    • 案例
    • 優缺點
    • 注入型別匹配的所有bean(重點)
  • 按照建構式進行自動注入
    • 用法
    • 案例
  • autowire=default
    • 用法
    • 案例
  • 總結

手動注入的不足

上篇文章中介紹了依賴注入中的手動注入,所謂手動注入是指在xml中采用硬編碼的方式來配置注入的物件,比如通過構造器注入或者set方法注入,這些注入的方式都存在不足,比如下面代碼:

public class A{
    private B b;
    private C c;
    private D d;
    private E e;
    ....
    private N n;

    //上面每個private屬性的get和set方法
}

使用spring容器來管理,xml配置如下:

<bean class="b" class="B"/>
<bean class="c" class="C"/>
<bean class="d" class="D"/>
<bean class="e" class="E"/>
<bean class="a" class="A">
    <property name="b" ref="b"/>
    <property name="c" ref="c"/>
    <property name="d" ref="d"/>
    <property name="e" ref="e"/>
    ...
</bean>

上面的注入存在的問題:

  • 如果需要注入的物件比較多,比如A類中有幾十個屬性,那么上面的property屬性是不是需要寫幾十個,此時組態檔代碼量暴增

  • 如果A類中新增或者洗掉了一些依賴,還需要手動去調整bean xml中的依賴配置資訊,否則會報錯

  • 總的來說就是不利于維護和擴展

為了解決上面這些問題,spring為我們提供了更強大的功能:自動注入

在介紹自動注入之前需要先介紹一些基礎知識,

Class.isAssignableFrom方法

用法

isAssignableFrom是Class類中的一個方法,看一下這個方法的定義:

public native boolean isAssignableFrom(Class<?> cls)

用法如下:

c1.isAssignableFrom(c2)

用來判斷c2和c1是否相等,或者c2是否是c1的子類,

案例

@Test
public void isAssignableFrom(){
    System.out.println(Object.class.isAssignableFrom(Integer.class)); //true
    System.out.println(Object.class.isAssignableFrom(int.class)); //false
    System.out.println(Object.class.isAssignableFrom(List.class)); //true
    System.out.println(Collection.class.isAssignableFrom(List.class)); //true
    System.out.println(List.class.isAssignableFrom(Collection.class)); //false
}

自動注入

自動注入是采用約定大約配置的方式來實作的,程式和spring容器之間約定好,遵守某一種都認同的規則,來實作自動注入,

xml中可以在bean元素中通過autowire屬性來設定自動注入的方式:

<bean id="" class="" autowire="byType|byName|constructor|default" />
  • byteName:按照名稱進行注入

  • byType:按型別進行注入

  • constructor:按照構造方法進行注入

  • default:默認注入方式

下面我們詳解每種注入方式的用法,

按照名稱進行注入(byName)

用法

autowire設定為byName

<bean id="" class="X類" autowire="byName"/>

spring容器會按照set屬性的名稱去容器中查找同名的bean物件,然后將查找到的物件通過set方法注入到對應的bean中,未找到對應名稱的bean物件則set方法不進行注入

需要注入的set屬性的名稱和被注入的bean的名稱必須一致,

來看看案例吧,

案例

DiByName.java

package com.javacode2018.lesson001.demo6;

/**
 * 按照名稱自動注入
 */
public class DiAutowireByName {
    public static class Service1 { //@1
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "Service1{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    public static class Service2 { //@1
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "Service2{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    private Service1 service1;//@3
    private Service2 service2;//@4

    public Service1 getService1() {
        return service1;
    }

    public void setService1(Service1 service1) {
        System.out.println("setService1->" + service1);
        this.service1 = service1;
    }

    public Service2 getService2() {
        return service2;
    }

    public void setService2(Service2 service2) {
        System.out.println("setService2->" + service2);
        this.service2 = service2;
    }

    @Override
    public String toString() {
        return "DiAutowireByName{" +
                "service1=" + service1 +
                ", service2=" + service2 +
                '}';
    }
}

這個類中有2個屬性,名稱為:

  • service1

  • service2

這兩個屬性都有對應的set方法,

下面我們在bean xml中定義2個和這2個屬性同名的bean,然后使用按照名稱進行自動注入,

diAutowireByName.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
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <bean id="service1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service1">
        <property name="desc" value="service1"/>
    </bean>
    <bean id="service2" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2"/>
    </bean>
    <bean id="service2-1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2-1"/>
    </bean>

    <!-- autowire:byName 配置按照name進行自動注入 -->
    <bean id="diAutowireByName1" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="byName"/>

    <!-- 當配置了自動注入,還可以使用手動的方式自動注入進行覆寫,手動的優先級更高一些 -->
    <bean id="diAutowireByName2" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="byName">
        <property name="service2" ref="service2-1"/>
    </bean>

</beans>

上面注釋認真看一下,

@1:定義了一個名稱為service1的bean

@2:定義了一個名稱為service2的bean

@3:定義diAutowireByName需要將autowire的值置為byName,表示按名稱進行自動注入,

spring容器創建diAutowireByName對應的bean時,會遍歷DiAutowireByName類中的所有set方法,然后得到set對應的屬性名稱串列:{“service1”,“service2”},然后遍歷這屬性串列,在容器中查找和屬性同名的bean物件,然后呼叫屬性對應的set方法,將bean物件注入進去

測驗用例

package com.javacode2018.lesson001.demo6;

import com.javacode2018.lesson001.demo5.IocUtils;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DiAutowireTest {

    /**
     * 按照名稱進行注入
     */
    @Test
    public void diAutowireByName() {
        String beanXml = "classpath:/com/javacode2018/lesson001/demo6/diAutowireByName.xml";
        ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
        System.out.println(context.getBean("diAutowireByName"));
    }
}

效果

運行diAutowireByName輸出:

setService1->Service1{desc='service1'}
setService2->Service2{desc='service2'}
setService2->Service2{desc='service2-1'}
setService1->Service1{desc='service1'}
DiAutowireByName{service1=Service1{desc='service1'}, service2=Service2{desc='service2'}}
DiAutowireByName{service1=Service1{desc='service1'}, service2=Service2{desc='service2-1'}}

優缺點

按名稱進行注入的時候,要求名稱和set屬性的名稱必須同名,相對于硬編碼的方式注入,確實節省了不少代碼,

按照型別進行自動注入

用法

autowire設定為byType

<bean id="" class="X類" autowire="byType"/>

spring容器會遍歷x類中所有的set方法,會在容器中查找和set引數型別相同的bean物件,將其通過set方法進行注入,未找到對應型別的bean物件則set方法不進行注入,

需要注入的set屬性的型別和被注入的bean的型別需要滿足isAssignableFrom關系,

按照型別自動裝配的時候,如果按照型別找到了多個符合條件的bean,系統會報錯,

set方法的引數如果是下面的型別或者下面型別的陣列的時候,這個set方法會被跳過注入:

Object,Boolean,boolean,Byte,byte,Character,char,Double,double,Float,float,Integer,int,Long,Short,shot,Enum,CharSequence,Number,Date,java.time.temporal.Temporal,java.net.URI,java.net.URI,java.util.Locale,java.lang.Class

來看看案例吧,

案例

DiByType.java

package com.javacode2018.lesson001.demo6;

/**
 * 按照型別自動注入
 */
public class DiAutowireByType {
    public static class Service1 {
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "Service1{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    public static class Service2 {
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "Service2{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    private Service1 service1;
    private Service2 service2;

    public Service1 getService1() {
        return service1;
    }

    public void setService1(Service1 service1) {
        System.out.println("setService1->" + service1); //@1
        this.service1 = service1;
    }

    public Service2 getService2() {
        return service2;
    }

    public void setService2(Service2 service2) {
        System.out.println("setService2->" + service2); //@2
        this.service2 = service2;
    }

    @Override
    public String toString() {
        return "DiByType{" +
                "service1=" + service1 +
                ", service2=" + service2 +
                '}';
    }
}

DiAutowireByType類中有2個set方法分別來注入Service1和Service2,兩個set方法中都輸出了一行文字,一會執行的時候可以通過這個輸出可以看出set方法是否被呼叫了,

diAutowireByName.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
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <bean id="service1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service1">
        <property name="desc" value="service1"/>
    </bean>
    <bean id="service2" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2"/>
    </bean>
    <bean id="service2-1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2-1"/>
    </bean>

    <!-- autowire:byName 配置按照name進行自動注入 -->
    <bean id="diAutowireByName1" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="byName"/>

    <!-- 當配置了自動注入,還可以使用手動的方式自動注入進行覆寫,手動的優先級更高一些 -->
    <bean id="diAutowireByName2" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="byName">
        <property name="service2" ref="service2-1"/>
    </bean>

</beans>

上面注釋認真看一下,

@1:定義了一個名稱為service1的bean

@2:定義了一個名稱為service2的bean

@3:定義diAutowireByName需要將autowire的值置為byName,表示按名稱進行自動注入,

spring容器創建diAutowireByName對應的bean時,會遍歷DiAutowireByName類中的所有set方法,然后得到set對應的屬性名稱串列:{“service1”,“service2”},然后遍歷這屬性串列,在容器中查找和屬性同名的bean物件,然后呼叫屬性對應的set方法,將bean物件注入進去

測驗用例

DiAutowireTest類中添加一個方法

/**
 * 按照set方法引數型別進行注入
 */
@Test
public void diAutowireByType() {
    String beanXml = "classpath:/com/javacode2018/lesson001/demo6/diAutowireByType.xml";
    ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
    System.out.println(context.getBean("diAutowireByType1"));
}

效果

運行diAutowireByType輸出:

setService1->Service1{desc='service1'}
setService2->Service2{desc='service2'}
DiByType{service1=Service1{desc='service1'}, service2=Service2{desc='service2'}}

優缺點

相對于手動注入,節省了不少代碼,新增或者洗掉屬性,只需要增減對應的set方法就可以了,更容易擴展了,

注入型別匹配的所有bean(重點)

按照型別注入還有2中比較牛逼的用法:

一個容器中滿足某種型別的bean可以有很多個,將容器中某種型別中的所有bean,通過set方法注入給一個java.util.List<需要注入的Bean的型別或者其父型別或者其介面>物件

將容器中某種型別中的所有bean,通過set方法注入給一個java.util.Map<String,需要注入的Bean的型別或者其父型別或者其介面>物件

來看個案例就懂了,

DiAutowireByTypeExtend.java

package com.javacode2018.lesson001.demo6;

import java.util.List;
import java.util.Map;

/**
 * 滿足條件的bean注入到集合中(重點)
 */
public class DiAutowireByTypeExtend {

    //定義了一個介面
    public interface IService1 {
    }

    public static class BaseServie {
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "BaseServie{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    //Service1實作了IService1介面
    public static class Service1 extends BaseServie implements IService1 {

    }

    //Service1實作了IService1介面
    public static class Service2 extends BaseServie implements IService1 {
    }

    private List<IService1> serviceList;//@1
    private List<BaseServie> baseServieList;//@2
    private Map<String, IService1> service1Map;//@3
    private Map<String, BaseServie> baseServieMap;//@4

    public List<IService1> getServiceList() {
        return serviceList;
    }

    public void setServiceList(List<IService1> serviceList) {//@5
        this.serviceList = serviceList;
    }

    public List<BaseServie> getBaseServieList() {
        return baseServieList;
    }

    public void setBaseServieList(List<BaseServie> baseServieList) {//@6
        this.baseServieList = baseServieList;
    }

    public Map<String, IService1> getService1Map() {
        return service1Map;
    }

    public void setService1Map(Map<String, IService1> service1Map) {//@7
        this.service1Map = service1Map;
    }

    public Map<String, BaseServie> getBaseServieMap() {
        return baseServieMap;
    }

    public void setBaseServieMap(Map<String, BaseServie> baseServieMap) {//@8
        this.baseServieMap = baseServieMap;
    }

    @Override
    public String toString() { //9
        return "DiAutowireByTypeExtend{" +
                "serviceList=" + serviceList +
                ", baseServieList=" + baseServieList +
                ", service1Map=" + service1Map +
                ", baseServieMap=" + baseServieMap +
                '}';
    }
}

@1,@2,@3,@4:定義了4個屬性,都是泛型型別的,都有對應的set方法,

@5:引數型別是List,這個集合集合中元素的型別是BaseServie,spring會找到容器中所有滿足BaseServie.isAssignableFrom(bean的型別)的bean串列,將其通過@5的set方法進行注入,

@6:同@5的代碼

@7:這個引數型別是一個map了,map的key是string型別,value是IService1型別,spring容器會將所有滿足IService1型別的bean找到,按照name->bean物件這種方式丟到一個map中,然后呼叫@7的set方法進行注入,最后注入的這個map就是bean的名稱和bean物件進行映射的一個map物件,

@8:同@7的代碼

@9:重寫了toString方法,輸出的時候好看一些

測驗用例

DiAutowireTest新增一個方法:

/**
 * 按照型別注入集合
 */
@Test
public void diAutowireByTypeExtend() {
    String beanXml = "classpath:/com/javacode2018/lesson001/demo6/diAutowireByTypeExtend.xml";
    ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
    //從容器中獲取DiAutowireByTypeExtend
    DiAutowireByTypeExtend diAutowireByTypeExtend = context.getBean(DiAutowireByTypeExtend.class);
    //輸出diAutowireByTypeExtend中的屬性看一下
    System.out.println("serviceList:" + diAutowireByTypeExtend.getServiceList());
    System.out.println("baseServieList:" + diAutowireByTypeExtend.getBaseServieList());
    System.out.println("service1Map:" + diAutowireByTypeExtend.getService1Map());
    System.out.println("baseServieMap:" + diAutowireByTypeExtend.getBaseServieMap());
}

效果

運行diAutowireByTypeExtend輸出:

serviceList:[BaseServie{desc='service1-1'}, BaseServie{desc='service1-2'}, BaseServie{desc='service2-1'}]
baseServieList:[BaseServie{desc='service1-1'}, BaseServie{desc='service1-2'}, BaseServie{desc='service2-1'}]
service1Map:{service1-1=BaseServie{desc='service1-1'}, service1-2=BaseServie{desc='service1-2'}, service2-1=BaseServie{desc='service2-1'}}
baseServieMap:{service1-1=BaseServie{desc='service1-1'}, service1-2=BaseServie{desc='service1-2'}, service2-1=BaseServie{desc='service2-1'}}

下面我們來介紹另外一種自動注入方式,

按照建構式進行自動注入

用法

autowire設定為constructor

<bean id="" class="X類" autowire="constructor"/>

spring會找到x類中所有的構造方法(一個類可能有多個構造方法),然后將這些構造方法進行排序(先按修飾符進行排序,public的在前面,其他的在后面,如果修飾符一樣的,會按照建構式引數數量倒敘,也就是采用貪婪的模式進行匹配,spring容器會盡量多注入一些需要的物件)得到一個建構式串列,會輪詢這個構造器串列,判斷當前構造器所有引數是否在容器中都可以找到匹配的bean物件,如果可以找到就使用這個構造器進行注入,如果不能找到,那么就會跳過這個構造器,繼續采用同樣的方式匹配下一個構造器,直到找到一個合適的為止,

來看看案例吧,

案例

DiAutowireByConstructor.java

package com.javacode2018.lesson001.demo6;

/**
 * 建構式的方式進行自動注入
 */
public class DiAutowireByConstructor {

    public static class BaseServie {
        private String desc;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "BaseServie{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }

    //Service1實作了IService1介面
    public static class Service1 extends BaseServie {
    }

    //Service1實作了IService1介面
    public static class Service2 extends BaseServie {
    }

    private Service1 service1;
    private Service2 service2;

    public DiAutowireByConstructor() { //@0
    }

    public DiAutowireByConstructor(Service1 service1) { //@1
        System.out.println("DiAutowireByConstructor(Service1 service1)");
        this.service1 = service1;
    }

    public DiAutowireByConstructor(Service1 service1, Service2 service2) { //@2
        System.out.println("DiAutowireByConstructor(Service1 service1, Service2 service2)");
        this.service1 = service1;
        this.service2 = service2;
    }

    public Service1 getService1() {
        return service1;
    }

    public void setService1(Service1 service1) {
        this.service1 = service1;
    }

    public Service2 getService2() {
        return service2;
    }

    public void setService2(Service2 service2) {
        this.service2 = service2;
    }

    @Override
    public String toString() {
        return "DiAutowireByConstructor{" +
                "service1=" + service1 +
                ", service2=" + service2 +
                '}';
    }
}

@1:1個引數的建構式

@2:2個引數的建構式

2個有參建構式第一行都列印了一段文字,一會在輸出中可以看到代碼是呼叫了那個建構式創建物件,

diAutowireByConstructor.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
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <bean class="com.javacode2018.lesson001.demo6.DiAutowireByConstructor$Service1">
        <property name="desc" value="service1"/>
    </bean>

    <bean id="diAutowireByConstructor" class="com.javacode2018.lesson001.demo6.DiAutowireByConstructor"
          autowire="constructor"/>

</beans>

測驗用例

DiAutowireTest新增一個方法

/**
 * 建構式的方式進行自動注入
 */
@Test
public void diAutowireByConstructor() {
    String beanXml = "classpath:/com/javacode2018/lesson001/demo6/diAutowireByConstructor.xml";
    ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
    System.out.println(context.getBean("diAutowireByConstructor"));
}

效果

運行diAutowireByConstructor輸出:

DiAutowireByConstructor(Service1 service1)
DiAutowireByConstructor{service1=BaseServie{desc='service1'}, service2=null}

從輸出中可以看到呼叫的是DiAutowireByConstructor類中的第一個建構式注入了service1 bean,

建構式匹配采用貪婪匹配,多個建構式結合容器找到一個合適的建構式,最匹配的就是第一個有參建構式,而第二個有參建構式的第二個引數在spring容器中找不到匹配的bean物件,所以被跳過了,

我們在diAutowireByConstructor.xml加入Service2的配置:

<bean class="com.javacode2018.lesson001.demo6.DiAutowireByConstructor$Service2">
    <property name="desc" value="service2"/>
</bean>

再來運行一下diAutowireByConstructor輸出:

DiAutowireByConstructor(Service1 service1, Service2 service2)
DiAutowireByConstructor{service1=BaseServie{desc='service1'}, service2=BaseServie{desc='service2'}}

此時可以看到第二個有參建構式被呼叫了,滿足了貪婪方式的注入原則,最大限度的注入所有依賴的物件,

autowire=default

用法

bean xml的根元素為beans,注意根元素有個default-autowire屬性,這個屬性可選值有(no|byName|byType|constructor|default),這個屬性可以批量設定當前檔案中所有bean的自動注入的方式,bean元素中如果省略了autowire屬性,那么會取default-autowire的值作為其autowire的值,而每個bean元素還可以單獨設定自己的autowire覆寫default-autowire的配置,如下:

<?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
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
       default-autowire="byName">

</beans>

案例

diAutowireByDefault.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
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
       default-autowire="byName"> //@1

    <bean id="service1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service1">
        <property name="desc" value="service1"/>
    </bean>
    <bean id="service2" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2"/>
    </bean>
    <bean id="service2-1" class="com.javacode2018.lesson001.demo6.DiAutowireByName$Service2">
        <property name="desc" value="service2-1"/>
    </bean>

    <!-- autowire:default,會采用beans中的default-autowire指定的配置 -->
    <bean id="diAutowireByDefault1" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="default"/> //@2

    <!-- autowire:default,會采用beans中的default-autowire指定的配置,還可以使用手動的方式自動注入進行覆寫,手動的優先級更高一些 -->
    <bean id="diAutowireByDefault2" class="com.javacode2018.lesson001.demo6.DiAutowireByName" autowire="default"> //@3
        <property name="service2" ref="service2-1"/>
    </bean>

</beans>

注意上面的@1配置的default-autowire=“byName”,表示全域默認的自動注入方式是:按名稱注入

@2和@3的autowire=default,那么注入方式會取default-autowire的值,

測驗用例

DiAutowireTest中新增一個方法

/**
 * autowire=default
 */
@Test
public void diAutowireByDefault() {
    String beanXml = "classpath:/com/javacode2018/lesson001/demo6/diAutowireByDefault.xml";
    ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
    System.out.println(context.getBean("diAutowireByDefault1"));
    System.out.println(context.getBean("diAutowireByDefault2"));
}

效果

運行diAutowireByDefault輸出

setService1->Service1{desc='service1'}
setService2->Service2{desc='service2'}
setService2->Service2{desc='service2-1'}
setService1->Service1{desc='service1'}
DiAutowireByName{service1=Service1{desc='service1'}, service2=Service2{desc='service2'}}
DiAutowireByName{service1=Service1{desc='service1'}, service2=Service2{desc='service2-1'}}

總結

xml中手動注入存在的不足之處,可以通過自動注入的方式來解決,本文介紹了3中自動注入:通過名稱自動注入、通過型別自動注入、通過構造器自動注入

按型別注入中有個比較重要的是注入匹配型別所有的bean,可以將某種型別所有的bean注入給一個List物件,可以將某種型別的所有bean按照bean名稱->bean物件的映射方式注入給一個Map物件,這種用法比較重要,用途比較大,要掌握

spring中還有其他自動注入的方式,用起來會更爽,后面的文章中我們會詳細介紹,

易兮科技 Java
18級大連海事大學在校生
網路工程 & 國際經濟與貿易 雙學位
中山市易兮軟體開發有限公司創始人
易兮科技團隊負責人
Java語言愛好者

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/183438.html

標籤:其他

上一篇:學習JavaWeb這一篇就夠了

下一篇:“HUAWEI”4面技術5面HR,基礎-專案-技術,Offer擦肩而過?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more