本文内容
-
手动注入的不足
-
Class.isAssignableFrom方法介绍
-
3种自动注入方式详解及案例
-
按名称自动注入
-
按类型自动注入
-
按构造器进行自动注入
-
按类型自动注入某种类型的所有bean给List和Map(重点)
-
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&#