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属性来设置自动注入的方式:
<bean id="" class="X类" autowire="byName|byType|constructor|default"/>
一、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文件增加配置
<!--先手动创建service1、service2对象--> <bean id="service1" class="com.java.spring01.demo5.AutowiredByName.Service1"> <property name="desc" value="byName-service1"/> </bean> <bean id="service2" class="com.java.spring01.demo5.AutowiredByName.Service2"> <property name="desc" value="byName-service2"/> </bean> <!--创建自动注入对象--> <bean id="autowiredByName" class="com.java.spring01.demo5.AutowiredByName" autowire="byName"/>
运行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文件中增加配置
<!--注意id值不需要同属性一致--> <bean id="service1-Type" class="com.java.spring01.demo5.AutowiredByType.Service1"> <property name="desc" value="byType-service1"/> </bean> <bean id="service2-Type" class="com.java.spring01.demo5.AutowiredByType.Service2"> <property name="desc" value="byType-service2"/> </bean> <bean id="autowiredByType" class="com.java.spring01.demo5.AutowiredByType" autowire="byType"/>
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<String,需要注入的Bean的类型或者其父类型或者其接口>对象
三、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,增加配置元数据信息
<bean id="service1-Constructor" class="com.java.spring01.demo5.AutowiredByConstructor.Service1"> <property name="desc" value="constructor-service1"/> </bean> <bean id="service2-Constructor" class="com.java.spring01.demo5.AutowiredByConstructor.Service2"> <property name="desc" value="constructor-service2"/> </bean> <bean id="service3-Constructor" class="com.java.spring01.demo5.AutowiredByConstructor.Service3"> <property name="desc" value="constructor-service3"/> </bean> <bean id="autowiredByConstructor" class="com.java.spring01.demo5.AutowiredByConstructor" autowire="constructor"/>
运行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属性。
原文:https://www.cnblogs.com/8593l/p/12886513.html