【Spring入門から実戦までのチュートリアル】第2章 Spring Configuration Bean

2.Spring Bean の構成

    Spring IoC コンテナーが管理するオブジェクトは Bean と呼ばれ、Bean は Spring 構成ファイルの情報に基づいて作成されます。いわゆる構成 Bean は、Spring の IOC コンテナーに管理対象のオブジェクトを伝えることです。

2.1 Bean を構成する方法

2.1.1 従来の XML 構成方法

Person.java:

public class Person {
    private String name;
    private int age;
    private double money;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                '}';
    }
}

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    bean标签:让spring创建一个对象并放置在IOC容器内,一个bean标签就对应某个类的一个对象
    属性:
        id: 该bean对象的唯一标识符,bean的名称,不能重复的
        class: 需要创建对象的类型的全限定名,Spring通过反射机制创建该类的对象(要求:该类必须拥有无参构造方法)
    -->
    <bean id="person1" class="com.newcapec.bean.Person"/>
    <bean id="person2" class="com.newcapec.bean.Person">
</beans>

属性の解決:

  • id : The name of the bean must be unique in the IOC container. 構成ファイルが分割されているか、後で注釈が使用されているかに関係なく、id を繰り返してはなりません; id が指定されていない場合、Spring は自動的に完全修飾されたものを使用しますBean の名前としてのクラスのクラス名。

  • class : Java クラスの完全修飾名。

BeanTest.java:

public class BeanTest {

    @Test
    public void testBeanXML(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Person p1 = (Person) ac.getBean("person1");
        System.out.println(p1);

        Person p2 = (Person) ac.getBean("person2");
        System.out.println(p2);

        //测试p1和p2是不是指向同一个地址
        System.out.println(p1 == p2);//false,验证一个Bean对应一个对象

        Person p3 = (Person) ac.getBean("person1");
        System.out.println(p1 == p3);//true
    }
}

2.1.2 Java アノテーションに基づく構成

    以下の章に注意してください。

2.1.3 クラスベースの Java Config

    以下の章に注意してください。

2.2 Bean をインスタンス化する方法

2.2.1 コンストラクターによる Bean のインスタンス化

    Spring IoC コンテナーは、デフォルトの空のコンストラクターまたはパラメーター化されたコンストラクターを使用して、リフレクション メカニズムを通じて Bean オブジェクトをインスタンス化できます。

2.2.2 ファクトリによる Bean のインスタンス化

    以下の章に注意してください。

2.2.3 FactoryBean インスタンス化 Bean

    以下の章に注意してください。

2.3 スプリングコンテナ

    IoC のアイデアは IoC コンテナに基づいて実装されており、IoC コンテナの最下層は実際には Bean ファクトリです。Spring フレームワークは、BeanFactory と ApplicationContext という 2 つの異なるタイプの IoC コンテナーを提供します。

2.3.1 ビーンファクトリー

    BeanFactory は IoC コンテナの基本的な実装であり、Spring が提供する最も単純な IoC コンテナであり、IoC コンテナの最も基本的な機能を提供し、org.springframework.beans.factory.BeanFactory インターフェースによって定義されます。

    BeanFactory は遅延読み込み機構を採用しており、コンテナが設定ファイルを読み込んでもすぐに Java オブジェクトが作成されるのではなく、プログラム内でオブジェクトが取得 (使用) されたときにのみ Java オブジェクトが作成されます。
    
    注: BeanFactory は、Spring によって使用される内部インターフェースであり、通常、開発者が使用するために提供されていません。 

2.3.2 アプリケーションコンテキスト

    ApplicationContext は、BeanFactory の拡張である BeanFactory インターフェースのサブインターフェースです。ApplicationContext は、BeanFactory に基づいて、AOP (アスペクト指向プログラミング)、国際化、トランザクション サポートなど、多くのエンタープライズ レベルの機能を追加します。

2.3.3 ApplicationContext の主な実装クラス

  • ClassPathXmlApplicationContext: クラスパスから構成ファイルをロードします。

  • FileSystemXmlApplicationContext: ファイル システムから構成ファイルを読み込みます。

  • WebApplicationContext: WEB アプリケーション用に特別に用意されており、WEB ルート ディレクトリからの相対パスから初期化できます。

2.3.4 コンテナーから Bean を取得する

  • getBean(String name) メソッドは、Bean ID を介してコンテナーから Bean オブジェクトを取得します。

  • getBean(Class requiredType) メソッドは、Bean の Class タイプを介してコンテナから Bean オブジェクトを取得します。

  • getBean(String name, Class requiredType) メソッドは、Bean の ID と Class タイプを介してコンテナーから Bean オブジェクトを取得します。

注: IOC コンテナにこのタイプのオブジェクトが複数格納されている場合、Bean オブジェクトは Class タイプから取得できません。

BeanTest.java

public class BeanTest {
    @Test
    public void testGetBean() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.参数为字符串类型
        Person p1 = (Person) ac.getBean("person1");
        System.out.println(p1);

        //2.参数为Class类型,缺点:当IOC容器中存在多个此类型对象时,抛出异常
        Person person = ac.getBean(Person.class);
        System.out.println(person);

        //3.参数为字符串类型+Class类型
        Person p2 = ac.getBean("person2", Person.class);
        System.out.println(p2);
    }
}

2.4 依存性注入

2.4.1 プロパティベースのインジェクション

    Bean の setter メソッドを介して、属性値を Bean のプロパティに注入できます。
    
    Spring で Bean をインスタンス化するプロセスでは、IoC コンテナーは最初にデフォルト コンストラクター (引数なしのコンストラクター) を呼び出して Bean (Java オブジェクト) をインスタンス化し、次に Java リフレクション メカニズムを介して Bean の setXxx() メソッドを呼び出して、プロパティ値 Bean に注入します。
    
    プロパティ注入にはセッター注入を使用します。一般的な手順は次のとおりです。
        1. Bean にデフォルトの引数なしコンストラクターを提供し (他のパラメーター コンストラクターがない場合は省略できます)、注入する必要があるすべてのプロパティを提供します。 setXxx() メソッド;
        2. Spring XML 構成ファイルで、<beans> とその子要素 ​​<bean> を使用して bean を定義します;
        3. <bean> 要素内の <property> 要素を使用して値を割り当てます各プロパティに対して、name 属性を使用して Bean のプロパティ名を指定し、value 属性または <value> サブタグを使用してプロパティ値を指定します。
        
    プロパティ注入は、実際のアプリケーションで最も一般的に使用される注入方法です。

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过setter方法注入属性值 -->
    <bean id="person" class="com.newcapec.bean.Person">
        <!--
        property标签:表示通过属性的set方法为属性赋值,也叫做依赖注入
        属性:
        	name: 对象中的属性名称
        	value: 属性值
        -->
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
        <property name="money">
            <value>3600.5</value>
        </property>
    </bean>
</beans>
public class DiTest {

    @Test
    public void testSet() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Person person = ac.getBean("person", Person.class);

        System.out.println(person);
    }
}

2.4.2 コンストラクターベースのメソッドインジェクション

    Bean のパラメーター化されたコンストラクターを介して、Bean のプロパティ注入を実装できます。
    
    コンストラクターを使用して属性注入を実装する一般的な手順は次のとおりです:
        1. パラメータ化されたコンストラクターを Bean に追加し、コンストラクターの各パラメーターは注入する必要がある属性を表します;
        
        2. Spring XML 構成ファイルで、<beans を渡します> その子要素 ​​<bean> は Bean を定義します。

        3. <bean> 要素内の <constructor-arg> 要素を使用して、コンストラクター内の属性に値を割り当てます. Bean コンストラクターにあるパラメーターと同じ数の <constructor-arg> を使用する必要があります.要素。

Car.java:

public class Car {
    private String name;
    private String type;
    private double price;
    private int doors;

    public Car(String name, String type, double price, int doors) {
        this.name = name;
        this.type = type;
        this.price = price;
        this.doors = doors;
    }

    public Car(String name, String type, int doors) {
        this.name = name;
        this.type = type;
        this.doors = doors;
    }

    public Car(String name, String type, double price) {
        this.name = name;
        this.type = type;
        this.price = price;
    }

    public Car(String n, String t) {
        this.name = n;
        this.type = t;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", price=" + price +
                ", doors=" + doors +
                '}';
    }
}

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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过构造方法注入属性值 -->
    <bean id="car1" class="com.newcapec.bean.Car">
        <!--
        constructor-arg : 表示创建该类型的对象时,使用的构造方法的参数
        属性:
            value : 构造方法的参数值
            index : 构造方法参数的索引
            type : 构造方法参数的类型
            name : 构造方法参数的名称
        -->
        <constructor-arg value="宝马"/>
        <constructor-arg value="轿车"/>
        <constructor-arg value="360000"/>
        <constructor-arg value="4"/>
    </bean>
</beans>
  • コンストラクターのパラメーターをインデックスで一致させる

<bean id="car2" class="com.newcapec.bean.Car">
    <constructor-arg value="越野" index="1"/>
    <constructor-arg value="奔驰" index="0"/>
    <constructor-arg value="4" index="3"/>
    <constructor-arg value="560000" index="2"/>
</bean>
  • コンストラクターのパラメーターを型ごとに一致させる

<bean id="car3" class="com.newcapec.bean.Car">
    <constructor-arg value="大众" type="java.lang.String"/>
    <constructor-arg value="商务车" type="java.lang.String"/>
    <constructor-arg value="290000" type="double"/>
</bean>
  • コンストラクターのパラメーターをパラメーター名で一致させる

<bean id="car4" class="com.newcapec.bean.Car">
    <constructor-arg value="电动车" name="t"/>
    <constructor-arg value="特斯拉" name="n"/>
</bean>

テスト:

public class DiTest {
    @Test
    public void testConstructor() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Car car1 = ac.getBean("car1", Car.class);
        System.out.println(car1);

        Car car2 = ac.getBean("car2", Car.class);
        System.out.println(car2);

        Car car3 = ac.getBean("car3", Car.class);
        System.out.println(car3);

        Car car4 = ac.getBean("car4", Car.class);
        System.out.println(car4);
    }
}

2.5 属性値の注入

2.5.1 リテラル値

  • 文字列で表すことができる値は、<value>label または value 属性を介して挿入できます。

  • リテラル値の注入は、基本データ型、ラッパー型、文字列、およびその他の型に使用できます。Spring は文字列を対応するデータ型に自動的に変換します。

  • リテラル値に特殊文字が含まれている場合は、 を使用して<![CDATA[]]>リテラル値をラップできます。

Person.java:

public class Person {
    private String name;
    private int age;
    private double money;
    private Date birthday;
    private boolean gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public boolean isGender() {
        return gender;
    }

    public void setGender(boolean gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                ", birthday=" + birthday +
                ", gender=" + gender +
                '}';
    }
}

applicationContext.xml:

<!--注入属性值:字面值-->
<bean id="per" class="com.newcapec.bean.Person">
    <property name="name" value="李四"/>
    <!--特殊值写法-->
    <!--<property name="name">
            <value><![CDATA[1<2]]></value>
        </property>-->
    <property name="age" value="20"/>
    <property name="money" value="3000.8"/>
    <!--对于日期值,如果写其他格式,不识别-->
    <property name="birthday" value="1998/05/12"/>
    <property name="gender" value="true"/>
</bean>

テスト:

@Test
public void testValue() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Person per = ac.getBean("per", Person.class);

    System.out.println(per);
}

2.5.2 他の Bean の参照

    アプリケーションを構成する Bean は、多くの場合、アプリケーションの機能を完了するために相互に協力する必要があります。Bean が相互にアクセスできるようにするには、Bean 構成ファイルで Bean への参照を指定する必要があります。

Customer.java:

public class Customer {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Order.java:

public class Order {
    private String orderNum;
    private double price;
    /**
     * 自定义类型的属性
     */
    private Customer customer;

    public Order() {
    }

    public Order(String orderNum, double price, Customer customer) {
        this.orderNum = orderNum;
        this.price = price;
        this.customer = customer;
    }

    public String getOrderNum() {
        return orderNum;
    }

    public void setOrderNum(String orderNum) {
        this.orderNum = orderNum;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderNum='" + orderNum + '\'' +
                ", price=" + price +
                ", customer=" + customer +
                '}';
    }
}
  • 2.5.2.1 内部 Bean メソッド

    <bean> 要素の <property> または <constructor-arg> 要素内の Bean を「内部 Bean」として定義します。

1. setter メソッドが内部 Bean を注入します。

    セッターを介して内部 Bean を注入できます。この時点で、再度 <bean> 要素を使用して <bean> タグの下の <property> 要素で内部 Bean を定義するだけで済みます。形式は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="outerBean" class="……">
        <property name="……" >
            <!-- 定义内部 Bean -->
            <bean class="……">
                <property name="……" value="……" ></property>
                ……
            </bean>
        </property>
    </bean>
</beans>

    注: 内部 Bean はすべて匿名であり、ID と名前を指定する必要はありません。指定しても IoC コンテナは Bean を識別するための識別子として使用せず、Bean の Scope タグを無視します。そのため、内部 Bean はほとんど常に匿名であり、常に外部 Bean とともに作成されます。内部 Bean は、それが存在する Bean 以外の他の Bean に注入することはできません。

<bean id="order1" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413001"/>
    <property name="price" value="998"/>
    <!--setter 方式注入内部 Bean-->
    <property name="customer">
        <bean class="com.newcapec.bean.Customer">
            <property name="username" value="tom"/>
            <property name="password" value="123456"/>
        </bean>
    </property>
</bean>

2. 内部 Bean を注入するコンストラクターの方法:

    コンストラクターを介して内部 Bean を注入できます。この時点で、再度 <bean> 要素を使用して、 <bean> タグの下の <constructor-arg> 要素で内部 Bean を定義するだけで済みます。形式は次のとおりです。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="……" class="……">
        <constructor-arg name="……">
            <!--内部 Bean-->
            <bean class="……">
                <constructor-arg name="……" value="……"></constructor-arg>
                ……
            </bean>
        </constructor-arg>
    </bean>
</beans>

applicationContext.xml:

<bean id="order2" class="com.newcapec.bean.Order">
    <constructor-arg name="orderNum" value="20220413002"/>
    <constructor-arg name="price" value="799"/>
    <!--构造函数方式注入内部 Bean-->
    <constructor-arg name="customer">
        <bean class="com.newcapec.bean.Customer">
            <property name="username" value="jack"/>
            <property name="password" value="123456"/>
        </bean>
    </constructor-arg>
</bean>
  • 2.5.2.2 ref属性の参照方法

    ref 属性は、名前に従って IOC コンテナーから指定された Bean を検索し、参照によって値を割り当てます。

1.<property>タグの ref 属性:

<bean id="customer3" class="com.newcapec.bean.Customer">
    <property name="username" value="jerry"/>
    <property name="password" value="123456"/>
</bean>
<bean id="order3" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413003"/>
    <property name="price" value="1299"/>
    <!-- 通过ref属性来注入属性值:其中ref属性的值为其他bean的id-->
    <property name="customer" ref="customer3"/>
</bean>

2.<property>タグ内の<ref>サブタグ:

<bean id="customer4" class="com.newcapec.bean.Customer">
    <property name="username" value="Spike"/>
    <property name="password" value="123456"/>
</bean>
<bean id="order4" class="com.newcapec.bean.Order">
    <property name="orderNum" value="20220413004"/>
    <property name="price" value="698"/>
    <!-- 通过ref子标签来注入其他的bean对象-->
    <property name="customer">
        <ref bean="customer4"/>
    </property>
</bean>

テスト:

@Test
public void testRef() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Order order1 = ac.getBean("order1", Order.class);
    System.out.println(order1);

    Order order2 = ac.getBean("order2", Order.class);
    System.out.println(order2);

    Order order3 = ac.getBean("order3", Order.class);
    System.out.println(order3);

    Order order4 = ac.getBean("order4", Order.class);
    System.out.println(order4);
}

2.5.3 コレクションのプロパティ

    Bean タグの下の <property> 要素で次の要素を使用して、List、Set、Map、Properties などの Java コレクション型のプロパティとパラメーターを構成することもできます。

ラベル 例証する
<list> タイプリストの値を注入するために使用され、繰り返しが可能になります。
<set> セット型の値を注入するために使用され、重複は許可されていません。
<map> キーと値の両方が任意の型である場合に、キーと値のコレクションを挿入するために使用されます。
<props> キーと値の両方が文字列型であるキーと値のコレクションを挿入するために使用されます。

    注: コレクション内の一般的なタイプの値については、値サブタグまたは値属性を介して直接注入できます. コレクション内のカスタム タイプの値については、ref タグまたは内部 Bean を介して注入する必要があります.

Course.java:

public class Course {
    private int id;
    private String cname;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", cname='" + cname + '\'' +
                '}';
    }
}

Student.java:

public class Student {
    private int id;
    private String name;
    private List<Course> courseList;
    private Integer[] ids;
    private Set<String> stringSet;
    private Map<String, Course> courseMap;
    private Properties props;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Course> getCourseList() {
        return courseList;
    }

    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }

    public Integer[] getIds() {
        return ids;
    }

    public void setIds(Integer[] ids) {
        this.ids = ids;
    }

    public Set<String> getStringSet() {
        return stringSet;
    }

    public void setStringSet(Set<String> stringSet) {
        this.stringSet = stringSet;
    }

    public Map<String, Course> getCourseMap() {
        return courseMap;
    }

    public void setCourseMap(Map<String, Course> courseMap) {
        this.courseMap = courseMap;
    }

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", courseList=" + courseList +
                ", ids=" + Arrays.toString(ids) +
                ", stringSet=" + stringSet +
                ", courseMap=" + courseMap +
                ", props=" + props +
                '}';
    }
}
  • 2.5.3.1 リスト収集

    java.util.List タイプのプロパティーを構成するには、いくつかの要素を含む <list> タグを指定する必要があります。これらのタグは、<value> を介して単純な定数値を指定し、<ref> を介して他の Bean への参照を指定できます。

<bean id="course1" class="com.newcapec.bean.Course">
    <property name="id" value="10"/>
    <property name="cname" value="Java语言"/>
</bean>
<bean id="course2" class="com.newcapec.bean.Course">
    <property name="id" value="20"/>
    <property name="cname" value="Oracle数据库"/>
</bean>
<bean id="course3" class="com.newcapec.bean.Course">
    <property name="id" value="30"/>
    <property name="cname" value="Spring框架"/>
</bean>

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <property name="courseList">
        <list>
            <ref bean="course1"/>
            <ref bean="course2"/>
            <ref bean="course3"/>
            <!--内部bean-->
            <bean class="com.newcapec.bean.Course">
                <property name="id" value="40"/>
                <property name="cname" value="Mybatis框架"/>
            </bean>
        </list>
    </property>
</bean>
@Test
public void testCollection() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    Student student = ac.getBean("student", Student.class);
    System.out.println(student);
}
  • 2.5.3.2 オブジェクト[]配列

    配列型のプロパティを構成するには、`<array>` タグを使用します。

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- 数组:array子标签-->
    <property name="ids">
        <array>
            <value>10</value>
            <value>20</value>
            <value>30</value>
            <value>40</value>
        </array>
    </property>
</bean>
  • 2.5.3.3 セットコレクション

    タイプ java.util.Set のプロパティを構成するには、`<set>` タグを使用します。

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- set集合:set子标签-->
    <property name="stringSet">
        <set>
            <value>hello</value>
            <value>goodbye</value>
            <value>how are you</value>
        </set>
    </property>
</bean>
  • 2.5.3.4 地図収集

    java.util.Map は `<map>` タグで定義され、`<map>` タグ内のサブタグとして複数の `<entry>` を使用できます。各 `<entry>` にはキーと値が含まれています。単純型は key および value 属性を使用して定義され、Bean 参照は key-ref および value-ref 属性を使用して定義されます。

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- map集合:map子标签-->
    <property name="courseMap">
        <map>
            <!--
            entry标签:表示Map集合中的一组键值对
            key: 表示Map集合中的键为字面值
            key-ref: 表示Map集合中的键为自定义类型
            value: 表示Map集合中的值为字面值
            value-ref: 表示Map集合中的值为自定义类型
            -->
            <entry key="one" value-ref="course3"/>
            <entry key="two" value-ref="course1"/>
        </map>
    </property>
</bean>
  • 2.5.3.5 プロパティ

    `<props>` を使用して java.util.Properties を定義します。このタグは複数の `<prop>` をサブタグとして使用します。各 `<prop>` タグはキー属性を定義する必要があります。

<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- Properties类型的属性 -->
    <property name="props">
        <props>
            <!-- prop标签,表示Properties集合中的一个键值对,key属性对应的键,prop开始标签与结束标签之后的区域填写值-->
            <prop key="hello">你好</prop>
            <prop key="goodbye">再见</prop>
        </props>
    </property>
</bean>
  • 2.5.3.6 シングルトン コレクション

    シングルトン コレクション: 複数の Bean で使用されます。`<util>` タグを使用して、Bean の外部でコレクションを定義します。

    注: util 名前空間とタグ仕様をインポートする必要があります。

xmlns:util="http://www.springframework.org/schema/util"

http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
<bean id="student" class="com.newcapec.bean.Student">
    <property name="id" value="1001"/>
    <property name="name" value="小明"/>
    <!-- 引入单例集合 -->
    <property name="courseList" ref="myList"></property>
</bean>

<!-- 外部集合:多个集合属性可同时引用 -->
<util:list id="myList">
    <ref bean="course1"/>
    <ref bean="course2"/>
    <ref bean="course3"/>
    <bean class="com.newcapec.bean.Course">
        <property name="id" value="40"/>
        <property name="cname" value="MySQL数据库"/>
    </bean>
</util:list>

2.5.4 短い名前空間の注入

    コンストラクターまたはセッター メソッドを介してプロパティ インジェクションを実行する場合、通常は <bean> 要素内に <property> および <constructor-arg> 要素をネストして実装します。このメソッドは明確な構造を持っていますが、書くのはもっと面倒です。

    Spring フレームワークは、次の表に示すように、Spring の XML 構成を簡素化できる 2 つの短い名前空間を提供します。

短い名前空間 簡素化された XML 構成 例証する
p 名前空間 <bean>要素内にネストされた<property>要素 セッタープロパティインジェクションのショートカット実装です
c 名前空間 <bean>要素内にネストされた<constructor>要素 コンストラクタ プロパティ インジェクションのショートカット実装です

部ジャバ:

public class Dept {
    private int deptno;
    private String dname;
    private String loc;

    public Dept() {
    }

    public Dept(int deptno, String dname, String loc) {
        this.deptno = deptno;
        this.dname = dname;
        this.loc = loc;
    }

    public int getDeptno() {
        return deptno;
    }

    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }
}

Emp.java:

public class Emp {
    private int empno;
    private String ename;
    /**
     * 关系属性
     */
    private Dept dept;

    public Emp() {
    }

    public Emp(int empno, String ename, Dept dept) {
        this.empno = empno;
        this.ename = ename;
        this.dept = dept;
    }

    public int getEmpno() {
        return empno;
    }

    public void setEmpno(int empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", dept=" + dept +
                '}';
    }
}
  • 2.5.4.1p 名前空間インジェクション

    p 名前空間は、セッター スタイルのプロパティ インジェクションのショートカット実装です。これにより、ネストされた <property> 要素を使用する代わりに、Bean プロパティの形式でセッター プロパティ インジェクションを実装して、Spring の XML 構成を簡素化するという目的を達成できます。

    まず、構成ファイルの <beans> 要素に次の XML 制約をインポートする必要があります。

xmlns:p="http://www.springframework.org/schema/p"

XML 制約をインポートした後、次の形式で属性注入を実装できます。

<bean id="Bean 唯一标志符" class="包名+类名" p:普通属性="普通属性值" p:对象属性-ref="对象的引用">

p 名前空間を使用して依存関係を注入する場合は、次の 3 つの点に注意する必要があります。

  • Java クラスには setter メソッドが必要です。

  • Java クラスにはパラメーターなしのコンストラクターが必要です (クラスにはパラメーター化されたコンストラクターは含まれず、パラメーターなしのコンストラクターはデフォルトで存在します)。

  • p 名前空間を使用して属性注入を実装する前に、 p 名前空間の XML 制約を XML 構成の<beans>要素。

applicationContext.xml:

<!-- 通过p命名空间的方式,来简化依赖注入 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="8000" p:ename="张三" p:dept-ref="dept"/>

テスト:

@Test
public void testPNameSpace() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    Emp emp = ac.getBean("emp", Emp.class);
    System.out.println(emp);
}
  • 2.5.4.2 c 名前空間の注入

    c 名前空間は、コンストラクター インジェクションのショートカットです。これにより、Spring の XML 構成を簡素化するという目的を達成するために、ネストされた <constructor-arg> 要素を使用する代わりに、コンストラクター メソッドの属性注入を <bean> 属性の形式で実現できます。

    まず、構成ファイルの <beans> 要素に次の XML 制約をインポートする必要があります。

xmlns:c="http://www.springframework.org/schema/c"

XML 制約をインポートした後、次の形式で属性注入を実装できます。

<bean id="Bean 唯一标志符" class="包名+类名" c:普通属性="普通属性值" c:对象属性-ref="对象的引用">

c 名前空間を使用して依存関係を注入する場合は、次の 2 つの点に注意する必要があります。

  • Java クラスには、対応するパラメーター化されたコンストラクターが含まれている必要があります。

  • c 名前空間を使用して属性注入を実装する前に、c 名前空間の XML 制約を XML 構成の<beans>要素。

applicationContext.xml:

<!-- 通过c命名空间的方式,来简化依赖注入 -->
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="employee" class="com.newcapec.bean.Emp" c:empno="7369" c:ename="李四" c:dept-ref="department"/>

テスト:

@Test
public void testCNameSpace() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    Emp emp = ac.getBean("employee", Emp.class);
    System.out.println(emp);
}

2.5.5 autowire 自動アセンブリ

    Bean と Bean の間の依存関係を確立する Spring の動作を「ワイヤリング」と呼びます。

    Spring の IOC コンテナーは強力ですが、それは単なる空のシェルであり、それ自体で組み立て作業を完了することはできません。必要に応じてアセンブリ作業を完了できるように、率先して Bean を配置し、Bean と Bean 間の依存関係を伝える必要があります。

    これまでの研究では、XML 構成の <constructor-arg> と <property> の ref 属性を使用して、Bean と Bean の間の依存関係を手動で維持していました。
    
    少数の Bean のみを含むアプリケーションの場合、このアプローチで十分です。しかし、アプリケーションの継続的な開発により、コンテナーに含まれる Bean がますます増え、Bean 間の依存関係がますます複雑になり、作成する XML 構成がますます複雑になり、ますます複雑になります。面倒。

    過度に複雑な XML 構成は可読性が低いだけでなく、記述時に非常にエラーが発生しやすく、開発者の開発効率が大幅に低下することがわかっています。この問題を解決するために、Spring フレームワークには「オートワイヤー」機能も用意されています。
    
    Spring の自動アセンブリ機能により、Spring コンテナは、特定の規則 (自動アセンブリ規則、5 つのタイプがあります) に従って、指定された Bean のアプリケーション コンテキスト (ApplicationContext コンテナ) から依存する Bean を見つけ、Bean 間の関係を自動的に確立できます。 . 依存関係。そして、このプロセスは <constructor-arg> および <property> 要素の ref 属性をまったく使用せずに行われます。

    Spring の自動アセンブリ機能は、Spring アプリケーションの XML 構成を効果的に簡素化できるため、構成が多数ある場合は、自動アセンブリを使用して作業負荷を軽減できます。

    Spring フレームワークは、デフォルトでは自動アセンブリをサポートしていません. 自動アセンブリを使用する場合は、Spring XML 構成ファイルで <bean> 要素の autowire 属性を設定する必要があります.

Spring は、次の表に示すように、autowire 属性の 5 つの値に対応する合計 5 つの自動アセンブリ ルールを提供します。

属性値 例証する
名前で 名前による自動配線。Spring は、Java クラスの object 属性の名前に従って、アプリケーション全体のコンテキスト ApplicationContext (IoC コンテナー) を調べます。Bean の id または name 属性値がこのオブジェクト属性の名前と同じである場合、この Bean を取得し、現在の Java クラス Bean との関連付け関係を確立します。
タイプ別 タイプ別オートワイヤー。Spring は、Java クラスのオブジェクト プロパティの型に従って、アプリケーション全体のコンテキスト ApplicationContext (IoC コンテナー) を調べます。Bean の class 属性値が object 属性の type と一致する場合、その Bean が取得され、現在の Java クラスの Bean に関連付けられます。
constructor byType パターンと似ていますが、コンストラクター パラメーター (依存関係) に適用され、コンテナー内にコンストラクター パラメーターと同じ型の Bean が見つからない場合は例外がスローされます。実際には、コンストラクターのパラメーターのデータ型に応じて、byType モードの自動アセンブリが実行されます。
デフォルト 上位要素によって<beans>設定された。
いいえ デフォルト値は、自動アセンブリが使用されないことを意味し、Bean の依存関係<constructor-arg><property>および 要素の ref 属性を介して定義する必要があります。
  • 2.5.5.1 autowire を使用しない (autowire="no")

    autowire="no" は自動アセンブリを使用しないことを意味します このとき、<bean> 要素の <constructor-arg> と <property> 要素の ref 属性によって Bean の依存関係を維持する必要があります。

  • 2.5.5.2 名前によるオートワイヤー (autowire="byName")

    `autowire="byName"` は、属性名による自動配線を意味します。XML ファイル内の Bean の ID または名前は、クラス内の属性名と同じでなければなりません。
    
    注: Bean の ID または名前がクラスの属性名と一致する必要がある場合は、自動的にアセンブルされます。そうでない場合は、デフォルト値になります。

<!-- 自动装配 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="王武" autowire="byName"/>
  • 2.5.5.3 タイプ別オートワイヤー (autowire="byType")

    `autowire="byType"` は、クラス内のオブジェクト属性のデータ型に従って自動配線することを意味します。XML ファイル内の Bean の id または名前がクラス内の属性名と異なっていても、Bean の class 属性の値がクラス内の object 属性と同じ型である限り、オートワイヤーは可能です。完了しました。
    
    注: 同じタイプの複数の Bean が同時に存在する場合、注入は失敗し、例外がスローされます。

<!-- 自动装配 -->
<bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
<bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

<bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="马六" autowire="byType"/>
  • 2.5.5.4 コンストラクターのオートワイヤー (autowire="constructor")

    autowire="constructor" は、Java クラスのコンストラクタに従って自動アセンブリを実行することを意味します。
    
    めったに使用されず、もはや実証されていません。

  • 2.5.5.5 デフォルトの自動配線モード (autowire="default")

    デフォルトでは、上位タグ <beans> で設定した自動アセンブル規則 (default-autowire) を使用してアセンブルし、Beans.xml の設定内容は次のとおりです。 

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" 
       default-autowire="byName">
    
    <!-- 自动装配 -->
    <bean id="dept" class="com.newcapec.bean.Dept" p:deptno="10" p:dname="研发部" p:loc="郑州"/>
    <bean id="department" class="com.newcapec.bean.Dept" c:deptno="20" c:dname="产品部" c:loc="杭州"/>

    <bean id="emp" class="com.newcapec.bean.Emp" p:empno="7689" p:ename="马六" autowire="default"/>
</beans>

XML 構成での Bean オートワイヤーの欠点:

  • ビーン構成ファイルでオートワイヤー用のオートワイヤー属性を設定すると、ビーンのすべてのプロパティがワイヤーリングされます。ただし、個々の属性をアセンブルするだけの場合、autowire 属性は十分に柔軟ではありません。

  • autowire 属性は、タイプまたは名前のいずれかでオートワイヤーされます。両方ではありません。

  • 通常、自動アセンブリ機能が実際のプロジェクトで使用されることはほとんどありません。これは、自動アセンブリ機能によってもたらされる利点と比較して、明確で明確な構成ドキュメントの方が説得力があるためです。

2.6 外部プロパティ ファイルの使用

名前空間とラベルの仕様を追加します。

xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

デシベルのプロパティ:

# Mysql相关配置
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root

外部プロパティ ファイルを導入します。

<!-- 读取外部的资源文件-->
<context:property-placeholder location="classpath:db.properties"/>

MyDataSource.java:

public class MyDataSource {
    private String driver;
    private String url;
    private String username;
    private String password;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

式を介してプロパティ ファイル内のデータにアクセスします。

<bean id="myDataSource" class="com.newcapec.bean.MyDataSource">
    <property name="driver" value="${jdbc.mysql.driver}"/>
    <property name="url" value="${jdbc.mysql.url}"/>
    <property name="username" value="${jdbc.mysql.username}"/>
    <property name="password" value="${jdbc.mysql.password}"/>
</bean>

テスト:

public class ReadPropertiesTest {

    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        MyDataSource myDataSource = ac.getBean("myDataSource", MyDataSource.class);
        System.out.println(myDataSource);
    }
}

2.7 Bean スコープ

    デフォルトでは、すべての Spring Bean はシングルトンです。つまり、Spring アプリケーション全体で Bean インスタンスは 1 つだけです。

    <bean> 要素に scope 属性を追加して、Spring Bean のスコープを構成できます。たとえば、Bean を取得するたびに新しい Bean インスタンスが必要な場合は、Bean のスコープ属性をプロトタイプとして定義する必要があります.Spring が毎回同じ Bean インスタンスを返す必要がある場合は、Bean のスコープ属性を定義する必要があります。シングルトンとして。

    Spring 5 は、次の表に示すように、合計 6 つのスコープを提供します。

行動範囲 説明
シングルトン デフォルト値、シングルトン モードIOC コンテナーが初期化時に Bean のインスタンスを作成し、コンテナーのライフサイクル全体で Bean のインスタンスが 1 つだけ作成されることを示します。
プロトタイプ プロトタイプ モードは、 IOC コンテナーが初期化時に Bean のインスタンスを作成しないが、使用されるたびに Bean の新しいインスタンスを作成することを意味します。
リクエスト HTTP リクエストごとに、コンテナーは Bean インスタンスを作成します。このスコープは、現在の HTTP リクエスト内でのみ有効です。
セッション 同じ HTTP セッションは Bean インスタンスを共有し、異なるセッションは異なる Bean インスタンスを使用します。このスコープは、現在の HTTP セッション内でのみ有効です。
応用 同じ Web アプリケーションが Bean インスタンスを共有し、このスコープは現在の ServletContext 内で有効です。singleton と同様ですが、singleton は各 IoC コンテナーに Bean インスタンスが 1 つだけ存在することを意味し、Web アプリケーションには複数の IoC コンテナーが存在する可能性がありますが、Web アプリケーションには ServletContext が 1 つしかないため、アプリケーションがWeb アプリケーションの Bean インスタンス 実際のシングルトン パターン。
ウェブソケット websocket のスコープは WebSocket であり、WebSocket 全体で有効です。

    注: 上記の 6 つの Bean スコープでは、シングルトンとプロトタイプを除いて、従来の Spring IoC コンテナー (ClassPathXmlApplicationContext など) で直接使用できます。残りは、Web ベースの ApplicationContext 実装 (XmlWebApplicationContext など) でのみ使用できます。それ以外の場合、IllegalStateException が発生します。投げられる。
    
    このセクションでは、シングルトンとプロトタイプの 2 つの Bean スコープについてのみ詳細に説明し、他の Bean スコープについては、後続のコースで紹介します。

Book.java:

public class Book {
    private int id;
    private String name;
    private double price;
    private String author;

    public Book(){
        System.out.println("Book对象被创建....");
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
    }
}

2.7.1 シングルトン

    singleton は、Spring コンテナーのデフォルトのスコープです。Bean のスコープがシングルトンの場合、Spring IoC コンテナーには共有 Bean インスタンスが 1 つだけ存在します。Bean インスタンスはキャッシュに格納され、ID が Bean 定義と一致する限り、Bean へのすべての要求と参照はキャッシュ内のオブジェクト インスタンスを返します。

    Bean 定義のスコープがシングルトンの場合、その Bean はシングルトン Bean と呼ばれます。Spring IoC コンテナーでは、シングルトン Bean が Bean を作成するデフォルトの方法です。これにより、オブジェクトをより適切に再利用し、オブジェクトを繰り返し作成するコストを節約できます。

    Spring 構成ファイルでは、<bean> 要素の scope 属性を使用して、Bean のスコープをシングルトンとして定義できます。構成方法は次のとおりです。

applicationContext.xml:

<!-- singleton -->
<bean id="book" class="com.newcapec.bean.Book" p:id="101" p:name="西游记"
      p:price="98.5" p:author="吴承恩" scope="singleton"/>

2.7.2 プロトタイプ

    Bean 定義のスコープがプロトタイプである場合、その Bean はプロトタイプ Bean と呼ばれます。プロトタイプ Bean の場合、Spring コンテナーは、Bean が要求されるたびに新しい Bean インスタンスを作成します。
    
    ある意味で、Spring IoC コンテナーは Java のプロトタイプ Bean の new オペレーターに相当します。Bean の作成のみを担当し、その後のライフサイクル管理はクライアント コードによって行われます。
    
    Spring 構成ファイルでは、<bean> 要素の scope 属性を使用して、Bean のスコープをプロトタイプとして定義できます。構成方法は次のとおりです。

<!-- prototype -->
<bean id="book" class="com.newcapec.bean.Book" p:id="101" p:name="西游记"
      p:price="98.5" p:author="吴承恩" scope="prototype"/>

テスト:

public class ScopeTest {
    @Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("------------分割线--------------");

        Book book1 = ac.getBean("book",Book.class);
        System.out.println(book1);
        Book book2 = ac.getBean("book",Book.class);
        System.out.println(book2);

        System.out.println(book1 == book2);
    }
}

2.8 Bean のライフサイクル

    従来の Java アプリケーションでは、Bean のライフサイクルは非常に単純で、Java キーワード new を使用して Bean をインスタンス化した後、その Bean を使用できます。Bean が長期間使用されない場合、Java は自動的にガベージ コレクションを実行します。

    対照的に、Spring の Bean のライフサイクルはより複雑です.Spring IOC コンテナは Bean のライフサイクルを管理できます.Spring では、Bean のライフサイクルの特定の時点でカスタムタスクを実行できます。 1. Bean ライフ
        サイクルのインスタンス化
        2. Bean 属性の割り当て
        3. Bean の初期化
        4. Bean の使用
        5. Bean の破棄Spring は         、Bean のスコープに応じて
        
    Bean の管理方法を選択します。
Spring IoC コンテナは、Bean がいつ作成され、いつ初期化され、いつ破棄されるかを正確に制御できます;
        プロトタイプ スコープの Bean の場合、Spring IoC コンテナはそれを作成し、Bean インスタンスをクライアント コード管理、Spring IoC コンテナーは、その有効期間が追跡されなくなります。

2.8.1 Spring ライフサイクル プロセス

    Spring Bean の完全なライフサイクルは、Spring IoC コンテナーの作成から始まり、最終的な Spring IoC コンテナーが Bean を破棄するまでです. 具体的なプロセスを下の図に示します.

Bean ライフサイクルの実行プロセス全体は、次のように記述されます。

  1. Spring が起動し、Spring で管理する必要がある Bean を見つけてロードし、Bean をインスタンス化します。

  2. Bean でプロパティ インジェクションを実行します。

  3. Bean が BeanNameAware インターフェースを実装する場合、Spring は Bean の setBeanName() メソッドを呼び出して、現在の Bean の id 値を渡します。

  4. Bean が BeanFactoryAware インターフェースを実装する場合、Spring は setBeanFactory() メソッドを呼び出して、現在のファクトリ インスタンスへの参照を渡します。

  5. Bean が ApplicationContextAware インターフェースを実装する場合、Spring は setApplicationContext() メソッドを呼び出して、現在の ApplicationContext インスタンスへの参照を渡します。

  6. Bean が BeanPostProcessor インターフェースを実装する場合、Spring はインターフェースの事前初期化メソッド postProcessBeforeInitialzation() を呼び出して Bean を処理します. これはここで非常に重要であり、Spring の AOP はそれを使用して実装されます.

  7. Bean が InitializingBean インターフェースを実装する場合、Spring は afterPropertiesSet() メソッドを呼び出します。

  8. 構成ファイルの init-method 属性を介して初期化メソッドが指定されている場合、初期化メソッドが呼び出されます。

  9. BeanPostProcessor が Bean に関連付けられている場合、Spring はインターフェースの初期化メソッド postProcessAfterInitialization() を呼び出します。この時点で、Bean はアプリケーション システムで使用する準備ができています。

  10. <bean>Bean のスコープが singleton として指定されている場合、その Bean を Spring IoC のバッファー プールに入れ、Spring の Bean のライフサイクル管理をトリガー<bean>します; Bean のスコープが でプロトタイプとして指定されている場合、その Bean は に渡されます呼び出し元が Bean のライフサイクルを管理し、Spring はもはや Bean を管理しません。

  11. Bean が DisposableBean インターフェースを実装している場合、Spring は destroy() メソッドを呼び出して Bean を破棄します; Bean の破棄メソッドが構成ファイルの destroy-method 属性で指定されている場合、Spring はこのメソッドを呼び出して Bean を破棄します。

2.8.2 カスタム Bean のライフサイクル

    いくつかのライフサイクル コールバック メソッドを指定して、Spring Bean ライフサイクルの特定の時点でいくつかのカスタム操作を完了し、Bean ライフサイクルを管理できます。

Bean ライフサイクル コールバックには、主に次の 2 つの方法があります。

  • 初期化コールバック メソッド: Spring Bean が初期化された後に呼び出され、いくつかのカスタム コールバック操作を実行します。

  • 破壊コールバック メソッド: Spring Bean が破壊される前に呼び出され、いくつかのカスタム コールバック操作を実行します。

次の 3 つの方法で、Bean のライフサイクル コールバック メソッドをカスタマイズできます。

  • インターフェイスを介して実装

  • XML 構成を介して実装

  • アノテーションを使用して実装

    Bean に複数のライフサイクル コールバック メソッドがある場合、優先順位は、アノテーション > インターフェース > XML 構成です。

Dog.java:

public class Dog {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }
}

applicationContext.xml:

<bean id="dog" class="com.newcapec.bean.Dog" p:name="旺财" p:owner="小明" p:age="5"/>

テスト:

public class LifeCycleTest {
    @Test
    public void testLifeCycle() {
        System.out.println("-------容器初始化阶段---------");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        System.out.println("-------对象使用阶段---------");
        Dog dog = ac.getBean("dog", Dog.class);
        System.out.println(dog);

        System.out.println("-------容器关闭阶段---------");
        //手动关闭容器
        ac.close();//ApplicationContext没有close()
    }
}
  • 2.8.2.1 インターフェースによる実装

    Spring Bean の Java クラスに InitializingBean および DisposableBean インターフェースを実装することで、Bean のライフサイクル コールバック メソッドを指定できます。
    
    注: 通常、この方法でライフサイクル コールバック メソッドを指定することはお勧めしません。この方法ではコードの結合が高くなるからです。

コールバック メソッド インターフェース 方法 例証する
初期化コールバック InitializingBean afterPropertiesSet() Spring Bean が初期化された後に呼び出され、いくつかのカスタム コールバック操作を実行する初期化コールバック メソッドを指定します。
コールバックを破壊する 使い捨て豆 破壊() Spring Bean が破棄される前に呼び出される破棄コールバック メソッドを指定し、いくつかのカスタム コールバック操作を実行します。

Dog.java:

public class Dog implements InitializingBean, DisposableBean {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }

    /**
     * 初始化回调逻辑
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(" 调用接口:InitializingBean,方法:afterPropertiesSet,无参数");
    }
    /**
     * 销毁回调逻辑
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println(" 调用接口:DisposableBean,方法:destroy,无参数");
    }
}
  • 2.8.2.2 XML 構成による実装

    Spring の XML 構成の <bean> 要素の init-method および destroy-method 属性を使用して、Bean のライフサイクル コールバック メソッドを指定することもできます。

XML 構成プロパティ 説明
初期化メソッド Spring Bean が初期化された後に呼び出され、いくつかのカスタム コールバック操作を実行する初期化コールバック メソッドを指定します。
破棄方法 Spring Bean が破棄される前に呼び出される破棄コールバック メソッドを指定し、いくつかのカスタム コールバック操作を実行します。

Dog.java:

public class Dog {
    private String name;
    private String owner;
    private int age;

    public Dog() {
        System.out.println("Dog对象被创建...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("调用setName方法....");
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        System.out.println("调用setOwner方法....");
        this.owner = owner;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("调用setAge方法....");
        this.age = age;
    }

    public void init(){
        System.out.println("Dog对象的初始化方法...");
    }
    
    public void destroy(){
        System.out.println("Dog对象的销毁方法...");
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }
}

applicationContext.xml:

<bean id="dog" class="com.newcapec.bean.Dog" p:name="旺财" p:owner="小明" p:age="5"  
      init-method="init" destroy-method="destroy"/>

2.9 Bean 間の関係

2.9.1 継承関係

  • Spring では継承された Bean の構成が可能であり、継承された Bean は親 Bean と呼ばれます。この親 Bean を継承する Bean は子 Bean と呼ばれます。

  • 子 Bean は、Bean のプロパティ構成を含む構成を親 Bean から継承します。

  • 子 Bean は、親 Bean から継承された構成をオーバーライドすることもできます。

  • 親 Bean は、構成テンプレートまたは Bean インスタンスとして使用できます。親 Bean をテンプレートとしてのみ使用する場合は、<bean>abstract 属性を true に設定して、Spring がこの Bean をインスタンス化しないようにすることができます。

  • <bean>要素のすべての属性が継承されるわけではありません例: autowire、abstract など。

  • 親 Bean のクラス属性を無視して (親 Bean オブジェクトを作成する必要はなく、子 Bean のテンプレートを提供するだけです)、子 Bean に独自のクラスを指定させ、同じ属性構成を共有することもできます。ただし、現時点では、abstract を true に設定する必要があります。

Animal.java:

public class Animal {
    private String name;
    private Integer age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

applicationContext.xml:

<!-- bean之间的继承关系 -->
<bean id="animal" class="com.newcapec.bean.Animal">
    <property name="name" value="动物"></property>
    <property name="age" value="10"></property>
</bean>
<bean id="dog" class="com.newcapec.bean.Dog" parent="animal">
    <property name="name" value="小狗"></property>
    <property name="owner" value="小黑"></property>
</bean>

テスト:

public class RelationTest {
    @Test
    public void testExtends() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Dog dog = ac.getBean("dog", Dog.class);
        System.out.println(dog);
    }
}

テンプレートを定義します。

    親 Bean の定義には、抽象属性という非常に重要な属性があります。親 Bean の abstract 属性値が true の場合、その Bean は抽象的であることを示します。

    抽象親 Bean は、テンプレートとして子 Bean にのみ継承でき、インスタンス化することも、他の Bean から参照することもできず、コード内の id に従って getBean() メソッドを呼び出して取得することもできません。そうでない場合、エラーが返されます。

    親 Bean の定義で、class 属性を指定するか、class 属性を指定しないでください。親 Bean 定義で class 属性が明示的に指定されていない場合、親 Bean の抽象属性は true でなければなりません。

applicationContext.xml:

<!-- bean模版 -->
<bean id="animal" abstract="true">
    <property name="name" value="动物"></property>
    <property name="age" value="10"></property>
</bean>

<bean id="dog" class="com.newcapec.bean.Dog" parent="animal">
    <property name="name" value="小狗"></property>
    <property name="owner" value="小黑"></property>
</bean>

2.9.2 依存関係

  • Spring では、ユーザーは、依存関係属性を介して Bean の事前依存 Bean を設定できます。事前依存 Bean は、Bean がインスタンス化される前に作成されます。

  • フロントが複数の Bean に依存している場合は、コンマまたはスペースで Bean 名を構成できます。

Address.java:

public class Address {
    public Address() {
        System.out.println("Address对象创建了....");
    }
}

ユーザー.java:

public class User {
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public User() {
        System.out.println("User对象创建了....");
    }

    @Override
    public String toString() {
        return "User{" +
                "address=" + address +
                '}';
    }
}

applicationContext.xml:

<!-- bean之间的依赖关系 -->
<bean id="user" class="com.newcapec.bean.User" p:address-ref="address" depends-on="address"/>

<bean id="address" class="com.newcapec.bean.Address"/>

テスト:

public class RelationTest {
    @Test
    public void testDependsOn(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        User user = ac.getBean("user", User.class);
        System.out.println(user);
    }
}

2.10 ファクトリ経由で Bean をインスタンス化する

2.10.1 静的ファクトリ

  • 静的ファクトリ メソッドを呼び出して Bean を作成すると、オブジェクト作成のプロセスが静的メソッドにカプセル化されます。クライアントがオブジェクトを必要とする場合、オブジェクト作成の詳細を気にせずに静的メソッドを呼び出すだけで済みます。

  • 静的メソッドによって作成された Bean を宣言するには、Bean の class 属性でファクトリ メソッドを所有するクラスを指定し、factory-method 属性でファクトリ メソッドの名前を指定する必要があります。最後に、<constrctor-arg>要素を使用してメソッド パラメータをメソッドに渡します。

Cat.java:

public class Cat {
    private String name;
    private int age;

    public Cat() {
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

CatStaticFactory.java:

/**
 * 一个用于创建cat对象的静态工厂
 */
public class CatStaticFactory {
    /**
     * 提供一个创建对象的静态方法
     */
    public static Cat getInstance(String name, int age){
        return new Cat(name, age);
    }
}

applicationContext.xml:

<!-- 静态工厂-->
<bean id="cat1" class="com.newcapec.factory.CatStaticFactory" factory-method="getInstance">
    <constructor-arg value="汤姆猫"/>
    <constructor-arg value="2"/>
</bean>

テスト:

public class FactoryTest {
    @Test
    public void testStaticFactory() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat1", Cat.class);
        System.out.println(cat);
    }
}

2.10.2 インスタンスファクトリー

  • オブジェクトの作成プロセスを別のオブジェクト インスタンスのメソッドにカプセル化します。クライアントがオブジェクトを要求する必要がある場合、オブジェクト作成の詳細を気にせずにインスタンス メソッドを呼び出すだけで済みます。

  • インスタンスファクトリメソッドで作成したBeanを宣言するには、<bean>factory-bean属性にファクトリメソッドを持つBeanを指定し、factory-method属性にファクトリメソッド名を指定します。最後に、<construtor-arg>タグを使用してメソッド パラメータをファクトリ メソッドに渡します。

CatInstanceFactory.java:

/**
 * 一个用于创建cat对象的实例工厂
 */
public class CatInstanceFactory {
    /**
     * 提供一个创建对象的非静态方法
     */
    public Cat getInstance(String name, int age){
        return new Cat(name, age);
    }
}

applicationContext.xml:

<!-- 实例工厂-->
<bean id="instanceFactory" class="com.newcapec.factory.CatInstanceFactory"/>

<bean id="cat2" factory-bean="instanceFactory" factory-method="getInstance">
    <constructor-arg value="波斯猫"/>
    <constructor-arg value="3"/>
</bean>

テスト:

public class FactoryTest {
    @Test
    public void testInstanceFactory() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat2", Cat.class);
        System.out.println(cat);
    }
}

2.11 FactoryBean は Bean をインスタンス化します

  • Spring には 2 種類の Bean があり、1 つは通常の Bean で、もう 1 つはファクトリー Bean である FactoryBean です。

  • ファクトリ Bean は通常の Bean とは異なり、返されるオブジェクトは指定されたクラスのインスタンスではなく、ファクトリ Bean の getObject メソッドによって返されるオブジェクトを返します。

CatFactoryBean.java:

public class CatFactoryBean implements FactoryBean<Cat> {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取对象
     */
    @Override
    public Cat getObject() throws Exception {
        return new Cat(name, age);
    }

    /**
     * 生成对象的Class类型
     */
    @Override
    public Class<?> getObjectType() {
        return Cat.class;
    }

    /**
     * 设置该对象是否为单例模式
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

applicationContext.xml:

<!-- FactoryBean配置bean -->
<bean id="cat3" class="com.newcapec.factory.CatFactoryBean">
    <property name="name" value="加菲猫"/>
    <property name="age" value="5"/>
</bean>

テスト:

public class FactoryTest {
    @Test
    public void testFactoryBean(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Cat cat = ac.getBean("cat3", Cat.class);
        System.out.println(cat);
    }
}

2.12<beans>一般的に使用される属性または要素のサブ要素

    XML 構成の <beans> 要素には、複数の属性またはサブ要素を含めることができます。一般的に使用される属性またはサブ要素を次の表に示します。

属性名 説明
ID Bean の一意の識別子、および Spring IoC コンテナーによる Bean の構成と管理は、このプロパティを通じて完了します。id の値は文字で始まる必要があり、文字、数字、アンダースコアなどの記号を使用できます。
名前 この属性は Bean の名前を表します. name 属性を介して同じ Bean に複数の名前を指定できます. 各名前はコンマまたはセミコロンで区切られます. Spring コンテナーは、name 属性を介してコンテナー内の Bean を構成および管理できます。
クラス この属性は、Bean の特定の実装クラスを指定します。これは、完全なクラス名、つまりクラスの完全修飾名でなければなりません。
範囲 Bean のスコープを示し、属性値は singleton (シングルトン)、prototype (プロトタイプ)、request、session、global Session のいずれかです。デフォルト値はシングルトンです。
コンストラクター引数 <bean>要素の子要素であり、この要素を介して構築パラメータを渡して、Bean のインスタンス化を実現できます。この要素の index 属性は構築パラメーターの通し番号 (0 から始まる) を指定し、type 属性は構築パラメーターの型を指定します。
財産 <bean>要素のサブ要素を使用して Bean インスタンスのセッター メソッドを呼び出し、プロパティに値を割り当て、プロパティ インジェクションを完了します。この要素の name 属性は、Bean インスタンスで対応するプロパティ名を指定するために使用されます。
参照 <property><constructor-arg> 等元素的子元索,用于指定对某个 Bean 实例的引用,即 <bean> 元素中的 id 或 name 属性。
value <property><constractor-arg> 等元素的子元素,用于直接指定一个常量值。
list 用于封装 List 或数组类型的属性注入。
set 用于封装 Set 类型的属性注入。
map 用于封装 Map 类型的属性注入。
entry <map> 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值。
init-method 容器加载 Bean 时调用该方法,类似于 Servlet 中的 init() 方法
destroy-method 容器删除 Bean 时调用该方法,类似于 Servlet 中的 destroy() 方法。该方法只在 scope=singleton 时有效
lazy-init 懒加载,值为 true,容器在首次请求时才会创建 Bean 实例;值为 false,容器在启动时创建 Bean 实例。该方法只在 scope=singleton 时有效

おすすめ

転載: blog.csdn.net/ligonglanyuan/article/details/124567965