首页 > 编程语言 > 详细

Spring第七篇:依赖的自动注入

时间:2020-05-20 15:02:20      阅读:45      评论:0      收藏:0      [点我收藏+]

  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‘}}

  注入类型匹配的所有bean(重点)

  按照类型注入还有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属性。

Spring第七篇:依赖的自动注入

原文:https://www.cnblogs.com/8593l/p/12886513.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!