Spring的依赖的手动注入,手动注入是在bean.xml文件中通过硬编码的形式,通过参数构造器的construct-arg方式或者setter方法的property方式来进行依赖的注入,存在明显的不足:
bean实例中依赖的属性较多时,bean.xml文件中配置元数据信息会相应暴增,而且对bean实例所属的类中进行修改,则需要对对应的bean.xml配置文件进行调整。使用手动注入的方式进行依赖管理,不利于代码的维护与扩展。
Class.isAssignableFrom方法
Class1.isAssignableFrom (Class2)调用者和参数都是 java.lang.Class 类型,用来判断Class1与Class2相同,或者Class1是否是Class2的超类。
test方法
@Test
public void test(){
System.out.println(List.class.isAssignableFrom(List.class));//true
System.out.println(List.class.isAssignableFrom(int.class));//false
System.out.println(List.class.isAssignableFrom(Object.class));//false
System.out.println(Object.class.isAssignableFrom(List.class));//true
}
Spring的自动注入:
自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。xml中可以在bean元素中通过autowire属性来设置自动注入的方式:
一、byName(通过名称注入)
创建class类型
public class AutowiredByName {
private Service1 service1;
private Service2 service2;
public AutowiredByName() {
}
public AutowiredByName(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 "AutowiredByName{" +
"service1=" + service1 +
", service2=" + service2 +
‘}‘;
}
//定义内部类
public static class Service1{
private String desc;
public Service1() {
}
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 Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
}
bean.xml文件增加配置
运行test方法
@Before
public void before(){
String beanXML = "classpath:/spring01/demo5/bean.xml";
context = new ClassPathXmlApplicationContext(beanXML);
}
@Test
public void test1(){
Object autowiredByName = context.getBean("autowiredByName");
if( AutowiredByName.class.isAssignableFrom(autowiredByName.getClass())){
System.out.println(autowiredByName);
}
}
test方法运行结果
AutowiredByName{service1=Service1{desc=‘byName-service1‘}, service2=Service2{desc=‘byName-service2‘}}
Spring容器创建autowried对象的时候,会遍历AutowiredByName类中的所有属性,得到service1、service2的属性列表。然后根据属性名在Spring容器中获取到相应的bean对象,调用AutowiredByName类的set方法将其注入到autowried的bean对象中。注入的时候会校验service1和service2的类型和AutowiredByName类中的属性类型是否一一对应。不对应会报出错误:
Caused by: java.lang.IllegalStateException: Cannot convert value of type
二、byType(根据类型注入)
Spring根据类型注入的时候会解析属性的类型然后调用set方法进行注入,当bean.xml文件中不存在对应类型的bean时,则不进行注入,若是多个相同类型的bean存在则会直接在xml文件中提示more than one bean of....
创建class类型
public class AutowiredByType {
private Service1 service1;
private Service2 service2;
public AutowiredByType() {
}
public AutowiredByType(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 "AutowiredByType{" +
"service1=" + service1 +
", service2=" + service2 +
‘}‘;
}
//定义内部类
public static class Service1{
private String desc;
public Service1() {
}
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 Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
}
bean.xml文件中增加配置
test方法
@Test
public void test2(){
System.out.println(context.getBean("autowiredByType"));
}
test方法运行结果
AutowiredByType{service1=Service1{desc=‘byType-service1‘}, service2=Service2{desc=‘byType-service2‘}}
按照类型注入还有2中比较牛逼的用法:
一个容器中满足某种类型的bean可以有很多个,将容器中某种类型中的所有bean,通过set方法注入给一个java.util.List<需要注入的Bean的类型或者其父类型或者其接口>对象
将容器中某种类型中的所有bean,通过set方法注入给一个java.util.Map
三、constructor(构造函数注入)
Spring会将类的所有构造函数筛选出来,将所有的构造函数进行排序(public的在前面,参数数量多的在前面),然后根据bean.xml中的配置文件采用贪婪原则进行匹配,尽可能多注入依赖的bean。
创建class对象
public class AutowiredByConstructor {
private Service1 service1;
private Service2 service2;
private Service3 service3;
public AutowiredByConstructor(Service1 service1) {
this.service1 = service1;
}
public AutowiredByConstructor(Service1 service1, Service2 service2, Service3 service3) {
this.service1 = service1;
this.service2 = service2;
this.service3 = service3;
}
//静态内部类
public static class Service1{
private String desc;
public Service1(String desc) {
this.desc = desc;
}
public Service1() {
}
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 Service2(String desc) {
this.desc = desc;
}
public Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
public static class Service3{
private String desc;
public Service3(String desc) {
this.desc = desc;
}
public Service3() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service3{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
@Override
public String toString() {
return "AutowiredByConstructor{" +
"service1=" + service1 +
", service2=" + service2 +
", service3=" + service3 +
‘}‘;
}
}
更改bean.xml,增加配置元数据信息
运行test方法及运行结果
@Test
public void test3(){
System.out.println(context.getBean("autowiredByConstructor"));
}
AutowiredByConstructor{service1=Service1{desc=‘constructor-service1‘}, service2=Service2{desc=‘constructor-service2‘}, service3=Service3{desc=‘constructor-service3‘}}
注意AutowiredByConstructor 类中有两个带参的构造函数,一个只需要Service1的参数,另一个需要全部的参数,当我们在bean.xml文件中将Service3的bean注释掉。则Spring容器创建对象的时候调用的是只有一个参数的构造函数。若是同一属性存在多个bean的话,则会跳过带有这个跟这些bean类型的参数的构造函数。
四、default(byType|byName|constructor)
bean.xml文件中的根元素beans中存在属性default-autowire,往这个属性上设置byType|byName|constructor值,就可以在bean中使用上autowired属性。