1.概述

转载:添加链接描述

2. 手动注入的不足

【Spring】Spring 依赖注入之手动注入

上篇文章中介绍了依赖注入中的手动注入,所谓手动注入是指在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>

上面的注入存在的问题:

  1. 如果需要注入的对象比较多,比如A类中有几十个属性,那么上面的property属性是不是需要写几十个,此时配置文件代码量暴增

  2. 如果A类中新增或者删除了一些依赖,还需要手动去调整bean xml中的依赖配置信息,否则会报错

  3. 总的来说就是不利于维护和扩展

为了解决上面这些问题,spring为我们提供了更强大的功能:自动注入

在介绍自动注入之前需要先介绍一些基础知识。

2.Class.isAssignableFrom方法

2.1 用法

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)); //trueSystem.out.println(Object.class.isAssignableFrom(int.class)); //falseSystem.out.println(Object.class.isAssignableFrom(List.class)); //trueSystem.out.println(Collection.class.isAssignableFrom(List.class)); //trueSystem.out.println(List.class.isAssignableFrom(Collection.class)); //false
}

3.自动注入

自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。

xml中可以在bean元素中通过autowire属性来设置自动注入的方式:

<bean id="" class="" autowire="byType|byName|constructor|default" />
byteName:按照名称进行注入byType:按类型进行注入constructor:按照构造方法进行注入default:默认注入方式

下面我们详解每种注入方式的用法。

3.1 按照名称进行注入(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 { //@1private String desc;public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}@Overridepublic String toString() {return "Service1{" +"desc='" + desc + '\'' +'}';}}public static class Service2 { //@1private String desc;public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}@Overridepublic String toString() {return "Service2{" +"desc='" + desc + '\'' +'}';}}private Service1 service1;//@3private Service2 service2;//@4public 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;}@Overridepublic String toString() {return "DiAutowireByName{" +"service1=" + service1 +", service2=" + service2 +'}';}
}

这个类中有2个属性,名称为:

service1service2

这两个属性都有对应的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/beanshttp://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;/*** 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!* xml中自动注入配置案例*/
public class DiAutowireTest {/*** 按照名称进行注入*/@Testpublic 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'}}

3.1.1 优缺点

按名称进行注入的时候,要求名称和set属性的名称必须同名,相对于硬编码的方式注入,确实节省了不少代码。

3.2 按照类型进行自动注入

用法
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;}@Overridepublic 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;}@Overridepublic 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); //@1this.service1 = service1;}public Service2 getService2() {return service2;}public void setService2(Service2 service2) {System.out.println("setService2->" + service2); //@2this.service2 = service2;}@Overridepublic 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/beanshttp://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;}@Overridepublic 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;//@1private List<BaseServie> baseServieList;//@2private Map<String, IService1> service1Map;//@3private Map<String, BaseServie> baseServieMap;//@4public List<IService1> getServiceList() {return serviceList;}public void setServiceList(List<IService1> serviceList) {//@5this.serviceList = serviceList;}public List<BaseServie> getBaseServieList() {return baseServieList;}public void setBaseServieList(List<BaseServie> baseServieList) {//@6this.baseServieList = baseServieList;}public Map<String, IService1> getService1Map() {return service1Map;}public void setService1Map(Map<String, IService1> service1Map) {//@7this.service1Map = service1Map;}public Map<String, BaseServie> getBaseServieMap() {return baseServieMap;}public void setBaseServieMap(Map<String, BaseServie> baseServieMap) {//@8this.baseServieMap = baseServieMap;}@Overridepublic String toString() { //9return "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);//从容器中获取DiAutowireByTypeExtendDiAutowireByTypeExtend 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'}}

下面我们来介绍另外一种自动注入方式。

3.3 按照构造函数进行自动注入

用法
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;}@Overridepublic 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) { //@1System.out.println("DiAutowireByConstructor(Service1 service1)");this.service1 = service1;}public DiAutowireByConstructor(Service1 service1, Service2 service2) { //@2System.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;}@Overridepublic 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/beanshttp://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'}}

此时可以看到第二个有参构造函数被调用了,满足了贪婪方式的注入原则,最大限度的注入所有依赖的对象。

3.4 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/beanshttp://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/beanshttp://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中还有其他自动注入的方式,用起来会更爽,后面的文章中我们会详细介绍。

【Spring】Spring 自动注入(autowire)详解相关推荐

  1. Spring Boot自动装配原理详解

    目录 1.环境和依赖 1.1.spring boot版本 1.2.依赖管理 2.自动装配 2.1.流程概述 2.2.三大步前的准备工作 2.2.1.注解入口 2.2.2.获取所有配置类 2.3.获取过 ...

  2. 无法获取未定义或 null 引用的属性“value”_SpringBoot之Spring@Value属性注入使用详解

    在使用Spring框架的项目中,@Value是使用比较频繁的注解之一,它的作用是将配置文件中key对应的值赋值给它标注的属性.在日常使用中我们常用的功能都比较简单,本篇文章系统的带大家来了解一下@Va ...

  3. spring的依赖注入方式详解

    第一种:使用setter注入 直接使用bean元素的子元素property进行相关的设置 ①简单类型,直接使用value进行赋值. <bean id="somebean" c ...

  4. Spring的注入方式详解

    [html] view plaincopy Spring的注入方式详解 Spring有三个注入方式,type1,type2,type3 type1  接口依赖 type2  setter/getter ...

  5. spring依赖注入原理详解(转载)

    spring依赖注入原理详解----转载 所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它.所 ...

  6. Spring Boot的启动器Starter详解

    Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...

  7. spring(7)---深入理解Spring核心技术——Spring中的各模块详解

    深入理解Spring核心技术--Spring中的各模块详解 Spring框架的两个基本概念IOC容器和AOP,相信大家现在对Spring中的这两个部分的基本概念有了一定的认识,好了,那么今天我们就来正 ...

  8. 【JAVA秘籍心法篇-Spring】Spring XML解析源码详解

    [JAVA秘籍心法篇-Spring]Spring XML解析源码详解 所谓天下武功,无坚不摧,唯快不破.但有又太极拳法以快制慢,以柔克刚.武功外式有拳打脚踢,刀剑棍棒,又有内功易筋经九阳神功.所有外功 ...

  9. Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!

    点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...

  10. Spring IoC自动装载autowire

    Spring IoC自动装载autowire 自动装载是Spring提供的一种更加简便的方式来完成DI(依赖注入),不需要手动配置property,IoC容器会自动选择bean完成注入. ⭐自动装载有 ...

最新文章

  1. FireFox 开始放弃 Flash:停止部分内容支持
  2. 随机蕨(Random Fern)
  3. ASP.NET MVC:通过 FileResult 向 浏览器 发送文件
  4. Part Five 音视频API
  5. 国产系统linux硬盘分区,Linux系统硬盘分区方案推荐
  6. 强大web打印控件下载 - 2019年最新支持所有浏览器-楚琳打印
  7. D类音频功放NS4110B电路设计
  8. 通达OA2016之进销存管理,为企业开启"精准营收"新模式
  9. 机器学习7个主要领域
  10. 从0开始学java-day08:eclipse的使用和超市管理系统案例
  11. 1小时,不会代码的我如何完成 网易云音乐 大作业网页制作?(IVX 第2篇)
  12. 切莫让这三只猫跑进管理工作中
  13. 【实例】用PHP制作一个简单的日历
  14. python实现多重排序(多级排序)
  15. function函数嵌套 matlab_MATLAB嵌套函数
  16. VMware虚拟机centos6.5最小化安装以及配置网络
  17. zr 10联测 day1
  18. 桌面IE图标不见了的4种解决方法
  19. 自定义Office中格式刷的快捷键
  20. 关于 android 里面的 AndroidX 和 annotation 冲突的解决方式

热门文章

  1. 荣耀V40将采用300Hz 触控采样率,1月18日正式发布!
  2. 小米高管称redmi暂没有曲面屏 网友:Redmi K40 Pro曲面屏无望了
  3. 性价比还是小米狠:两场下来友商完败?
  4. 华为麦芒9正式亮相:6400万三摄,2199元起
  5. 疑似荣耀X10 Max巨屏新机入网:5000mAh电池+22.5W快充
  6. 微信深色模式最大的槽点终于被干掉了,这一次安卓用户先享受!
  7. 迪士尼确认《花木兰》档期:7月24日北美等多地上映
  8. 堪称奇迹!8 天诞生一个产品,这家创业公司做到了
  9. 罗永浩确认12月初开发布会 不是手机也不是电子烟
  10. “华为鸿蒙”操作系统下月发布?华为辟谣:请以官方声明为准