zoukankan      html  css  js  c++  java
  • [Js-Spring]基于 XML 的 DI

    注入分类

    (1)设值注入:先调用 Bean 的无参构造函数,然后通过 setter 方法传入被调用者的实例。

    <!-- bean definitions here -->
    <bean id="mySchool" class="com.neu.di01.School">
        <property name="sname" value="neu"></property>
    </bean>
    <bean id="myStudent" class="com.neu.di01.Student">
        <property name="name" value="js"></property>
        <property name="age" value="23"></property>
        <property name="school" ref="mySchool"></property>
    </bean>

    注:对于其他 Bean 对象的引用,除了<bean/>标签的 ref 属性外,还可以使用 <ref/> 标签

    (2)构造注入:在构造调用者实例的同时,完成了被调用者的实例化。即使用构造器设置依赖关系

    <constructor-arg> 标签中用于指定参数的属性:

    name:指定参数名称

    index:指明该参数对应构造器的第几个参数,从0开始,不过该属性可以不需要,但是需要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致

       另外,type属性可用于指定类型,基本类型直接写类型关键字即可,非基本类型需要写全限定性类名

    <!-- bean definitions here -->
    <bean id="mySchool" class="com.neu.di02.School">
        <property name="sname" value="neu"></property>
    </bean>
    <bean id="myStudent" class="com.neu.di02.Student">
        <constructor-arg name="name" value="js"></constructor-arg>
        <constructor-arg name="age" value="22"></constructor-arg>
        <constructor-arg name="school" ref="mySchool"></constructor-arg>
        <!-- 
        <constructor-arg value="js"></constructor-arg>
        <constructor-arg value="22"></constructor-arg>
        <constructor-arg ref="mySchool"></constructor-arg>
         -->
        <!-- 
        <constructor-arg index="0" value="js"></constructor-arg>
        <constructor-arg index="1" value="22"></constructor-arg>
        <constructor-arg index="2" ref="mySchool"></constructor-arg>
         -->
    </bean>

    (3)特定接口注入:采用了侵入式编程,污染了代码,几乎不用

     命名空间注入(了解)

    对于设值注入和构造注入,除了使用 <property/>或<constructor-arg/>标签外,还可以使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现。根据注入实现方式的不同,分别以 p 命名空间和 c 命名空间注入。

    p 命名空间注入:采用设值注入,需要相应的 setter 方法

    c 命名空间注入:采用构造注入,需要相应的构造器

    (1)p 命名空间注入

    采用约束

    xmlns:p="http://www.springframework.org/schema/p"
    <!-- bean definitions here -->
    <bean id="mySchool" class="com.neu.di03.School" p:sname="北京大学"></bean>
    <bean id="myStudent" class="com.neu.di03.Student" p:name="张三"
        p:age="22" p:school-ref="mySchool"></bean>

    (2)c 命名空间注入

    采用约束

    xmlns:c="http://www.springframework.org/schema/c"
    <!-- bean definitions here -->
    <bean id="mySchool" class="com.neu.di04.School">
        <property name="sname" value="清华大学"></property>
    </bean>
    <bean id="myStudent" class="com.neu.di04.Student" c:name="张三"
        c:age="22" c:school-ref="mySchool"></bean>

    集合属性注入

     分别为数组,List,Set,Map,Properties注入值,例子如下,

    School.java

    package com.neu.di05;
    
    public class School {
        private String sname;
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        @Override
        public String toString() {
            return "School [sname=" + sname + "]";
        }
    }

    Some.java

    package com.neu.di05;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    public class Some {
        private School[] schools;
        private List<String> myList;
        private Set<String> mySet;
        private Map<String, Object> myMap;
        private Properties myPros;
    
        public void setSchools(School[] schools) {
            this.schools = schools;
        }
    
        public void setMyList(List<String> myList) {
            this.myList = myList;
        }
    
        public void setMySet(Set<String> mySet) {
            this.mySet = mySet;
        }
    
        public void setMyMap(Map<String, Object> myMap) {
            this.myMap = myMap;
        }
    
        public void setMyPros(Properties myPros) {
            this.myPros = myPros;
        }
    
        @Override
        public String toString() {
            return "Some [schools=" + Arrays.toString(schools) + ", myList=" + myList + ", mySet=" + mySet + ", myMap="
                    + myMap + ", myPros=" + myPros + "]";
        }
    
    }

    applicationContext.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" xmlns:c="http://www.springframework.org/schema/c"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <!-- bean definitions here -->
        <bean id="school1" class="com.neu.di05.School">
            <property name="sname" value="清华大学"></property>
        </bean>
        <bean id="school2" class="com.neu.di05.School">
            <property name="sname" value="北京大学"></property>
        </bean>
        <bean id="some" class="com.neu.di05.Some">
            <property name="schools">
                <array>
                    <ref bean="school1" />
                    <ref bean="school2" />
                </array>
            </property>
            <property name="myList">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                </list>
            </property>
            <property name="mySet">
                <set>
                    <value>北京</value>
                    <value>上海</value>
                </set>
            </property>
            <property name="myMap">
                <map>
                    <entry key="QQ" value="123"></entry>
                    <entry key="WeiXin" value="456"></entry>
                </map>
            </property>
            <property name="myPros">
                <props>
                    <prop key="地址">辽宁省沈阳市</prop>
                    <prop key="名称">neu</prop>
                </props>
            </property>
        </bean>
    
    </beans>

    applicationContext.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" xmlns:c="http://www.springframework.org/schema/c"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <!-- bean definitions here -->
        <bean id="school1" class="com.neu.di06.School">
            <property name="sname" value="清华大学"></property>
        </bean>
        <bean id="school2" class="com.neu.di06.School">
            <property name="sname" value="北京大学"></property>
        </bean>
        <bean id="some" class="com.neu.di06.Some">
            <property name="schools">
                <array>
                    <ref bean="school1" />
                    <ref bean="school2" />
                </array>
            </property>
            <property name="arrays" value="aaa,bbb"></property>
            <property name="myList" value="张三s,李四"></property>
            <property name="mySet" value="北京,上海"></property>
            <property name="myMap">
                <map>
                    <entry key="QQ" value="123"></entry>
                    <entry key="WeiXin" value="456"></entry>
                </map>
            </property>
            <property name="myPros">
                <props>
                    <prop key="地址">辽宁省沈阳市</prop>
                    <prop key="名称">neu</prop>
                </props>
            </property>
        </bean>
    
    </beans>

    MyTest.java

    package com.neu.di05;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        @Test
        public void test01() {
            // 加载Spring配置文件,创建Spring容器对象
            String resource = "com/neu/di05/applicationContext.xml";
            ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
            // 从容器中获取指定的Bean对象
            Some some = (Some) ac.getBean("some");
            System.out.println(some);
            ((ClassPathXmlApplicationContext) ac).close();
        }
    }

    对于域属性的自动注入

    byName 方式自动注入

    配置文件中被调用者的 Bean 的 id 值与代码中调用者 Bean 的属性名相同时,可以使用 byName 的方式,让容器自动将被调用者 Bean 注入给调用者 Bean 。

    如图中 id 为 school 的 Bean,正好对应 Student 类中定义的 school 成员变量,在 id 为 myStudent 的 Bean 中直接定义自动注入方式 autowrite=“byName” 即可

    byType 方式自动注入

    配置文件中被调用者Bean的class属性指定的类,必须要与代码中被调用者Bean类的某域属性同源,即,相同或者具有is-a关系(子类,或者实现类)。同源的被调用者Bean只能有一个,多于一个则会报错,不知道该匹配哪一个。

    使用SPEL表达式

    SPEL(Spring Expression Language),即 Spring EL 表达式语言。即,在 Spring 配置文件中为 Bean 的属性注入值的时候,可以直接使用 SPEL 表达式计算结果。SPEL表达式以#开头,后加一对大括号。

    用法:<bean id="abc" value="#{…}" />。

    Person.java

    package com.neu.di10;
    
    public class Person {
        private String pname;
        private int page;
    
        // getter and setter
    
        // 计算年龄,大于25岁则按照25岁计算
        public int computeAge() {
            return this.page > 25 ? 25 : this.page;
        }
        
        // toString
    
    }

    Student.java

    package com.neu.di10;
    
    public class Student {
        private String name;
        private int age;
    
        // getter and setter
    
        // toString
    
    }

    applicationContext.xml 中的配置

    <bean id="myPerson" class="com.neu.di10.Person">
        <property name="pname" value="wx"></property>
        <property name="page" value="#{T(java.lang.Math).random()*50}"></property>
    </bean>
    <bean id="myStudent" class="com.neu.di10.Student">
        <property name="name" value="#{myPerson.pname}"></property>
        <property name="age" value="#{myPerson.computeAge()}"></property>
    <!-- <property name="age" value="#{myPerson.page>25?25:myPerson.page}"></property> -->
    </bean>

    上面仅仅是个例子,具体详细的所有用法可以查看框架解压包下面的 spring-framework-4.2.1.RELEASEdocsspring-framework-referencehtmlsingleindex.html 中查找 SPEL 用法

    框架包百度云链接 密码是 ycgm

    使用内部 Bean 注入

    当我们不希望代码直接访问某个 bean,即在代码中通过 getBean 方法获取该 Bean 实例,则可以将该 Bean 的定义放入调用者 bean 定义的内部,例子,

    匿名 Bean(虽然无法在代码中通过 getBean() 方法获取,但是可以通过类型自动注入)

    <!-- 匿名Bean -->
    <bean class="com.neu.di11.School">
        <property name="sname" value="neu"></property>
    </bean>
    <bean id="myStudent" class="com.neu.di11.Student" autowire="byType">
        <property name="name" value="js"></property>
        <property name="age" value="23"></property>
    </bean>

    内部匿名Bean

    <!-- 内部匿名bean -->
    <bean id="myStudent" class="com.neu.di12.Student" autowire="byType">
        <property name="name" value="js"></property>
        <property name="age" value="23"></property>
        <property name="school">
            <bean class="com.neu.di12.School">
                <property name="sname" value="neu"></property>
            </bean>
        </property>
    </bean>

    使用同类抽象 Bean 注入

    当若干的 Bean 实例同属于一个类,这些实例的属性值又有相同值,我们考虑使用抽象 Bean 来避免冗余,简化配置文件

    抽象 Bean 是用于让其他的 bean 继承的。这个 bean 不能通过 getBean() 方法来获取,所以应该设置 abstract 属性为 true,其默认值是 false(不设置为抽象 Bean 也能被继承,但一般应该设置为抽象的)

    Student 的部分代码

    public class Student {
        private String name;
        private int age;
        private String school;
        private String department;
    <!-- 同类抽象Bean -->
    <bean id="baseStudent" class="com.neu.di13.Student" abstract="true">
        <property name="school" value="清华大学"></property>
        <property name="department" value="计算机学院"></property>
    </bean>
    <bean id="student1" parent="baseStudent">
        <property name="name" value="JS"></property>
        <property name="age" value="21"></property>
    </bean>
    <bean id="student2" parent="baseStudent">
        <property name="name" value="WY"></property>
        <property name="age" value="22"></property>
    </bean>
    <bean id="student3" parent="baseStudent">
        <property name="name" value="WX"></property>
        <property name="age" value="20"></property>
    </bean>

    使用异类抽象 Bean 注入

    这种注入应用的情况是若干不同类的对象具有相同的属性,值也相同时。

    Student 类的成员变量如之前的同类抽象一样

    这是 Teacher 的部分代码(年龄变成了工龄)

    public class Teacher {
        private String name;
        private int workAge;
        private String school;
        private String department;
    <!-- 异类抽象Bean -->
    <bean id="base" abstract="true">
        <property name="school" value="清华大学"></property>
        <property name="department" value="计算机学院"></property>
    </bean>
    <bean id="student" class="com.neu.di14.Student" parent="base">
        <property name="name" value="JS"></property>
        <property name="age" value="21"></property>
    </bean>
    <bean id="teacher" class="com.neu.di14.Teacher" parent="base">
        <property name="name" value="JS"></property>
        <property name="workAge" value="5"></property>
    </bean>
  • 相关阅读:
    【java】对象赋值给另一个对象
    spring boot系列(五)spring boot 配置spring data jpa (查询方法)
    Spring Data JPA 查询
    Spring Data JPA 介绍
    OpenID简介
    OAUTH协议介绍
    URL encoding(URL编码)
    RESTful 介绍
    spring boot系列(四)spring boot 配置spring data jpa (保存修改删除方法)
    spring boot 启动报 java.lang.NoClassDefFoundError: ch/qos/logback/core/spi/LifeCycle 错误
  • 原文地址:https://www.cnblogs.com/jiasq/p/8600731.html
Copyright © 2011-2022 走看看