# 实例化 Bean 的三种方式

### 基于构造方法对象实例化

工作中，绝大多数场景都可以使用 基于构造方法对象实例化。在Apple 类中新增 price 属性 ，getter， setter方法，和对应的 4参数 构造方法。

```java
public class Apple {
    private String title;
    private String color;
    private String origin;
    private float price;

    public Apple(String title, String color, String origin) {
        System.out.println("使用带参构造方法(3个参数)创建对象," + this);
        this.title = title;
        this.color = color;
        this.origin = origin;
    }

    public Apple(String title, String color, String origin, float price) {
        System.out.println("使用带参构造方法(4个参数)创建对象 : " + this);
        this.title = title;
        this.color = color;
        this.origin = origin;
        this.price = price;
    }

    public Apple() {
        System.out.println("使用无参构造方法创建对象 : " + this);
    }

    public float getPrice() {
        return price;
    }

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

     // 其他部分与上一节相同。


}
```

在 applicationContext.xml 中增加下面3个 bean。

```java
    <!-- bean 标签默认通过默认构造方法创建对象 -->
    <bean id="apple1" class="indi.chester.spring.ioc.entity.Apple">

    </bean>

    <!-- bean 可以通过参数个数自动选择合适的构造方法 -->
    <bean id="apple2" class="indi.chester.spring.ioc.entity.Apple">
        <constructor-arg name="title" value="红富士"/>
        <constructor-arg name="color" value="红色"/>
        <constructor-arg name="origin" value="欧洲"/>
    </bean>

    <!-- bean 可以通过参数个数自动选择合适的构造方法 -->
    <bean id="apple3" class="indi.chester.spring.ioc.entity.Apple">
        <constructor-arg name="title" value="红富士"/>
        <constructor-arg name="color" value="红色"/>
        <constructor-arg name="origin" value="欧洲"/>
        <constructor-arg name="price" value="9.9"/>
    </bean>
```

Spring IoC 会根据 bean 中的参数个数，自动 选择对应的构造方法。类的创建顺序和 bean 的顺序相同。

### 基于静态工厂实例化

创建一个工厂类，工厂里面有一个静态方法，在静态方法中创建好对象，然后return 给 Spring IoC.

```java
package indi.chester.spring.ioc.factory;

import indi.chester.spring.ioc.entity.Apple;

//静态工厂通过静态方法创建对象, 隐藏创建对象的细节
public class AppleStaticFactory {
    public static Apple createSweetApple(){
        Apple apple =new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        System.out.println("通过静态方法创建对象 : "+apple);
        return apple;
    }
}
```

在 applicationContext.xml中加入一个 新的 bean

```java
<!-- bean 可以通过静态工厂创建对象 -->
<bean id="apple4" class="indi.chester.spring.ioc.factory.AppleStaticFactory" factory-method="createSweetApple"/>
```

在调用对象时和 基于 构造方法创建对象一样，直接使用 applicationContext 对象 的 getBean 方法获取即可。

### 基于工厂实例方法实例化

在Spring IoC容器中定义一个bean(工厂实例)，在工厂实例中定义一个方法return 对象。在定义一个 bean 通过对工厂实例 bean 创建对象。&#x20;

```java
//工厂实例方法是指 IoC容器对工厂进行实例化并调用 对应的实例方法创建 对象
public class AppleFactoryInstance {
    public Apple createSweetApple(){
        Apple apple =new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        System.out.println("通过工厂实例方法创建对象 : " + apple);
        return apple;
    }
}
```

在 applicationContext.xml中加入两个 bean

```xml
<!-- 利用工厂实例方法获取对象 -->
    <bean id="factoryInstance" class="indi.chester.spring.ioc.factory.AppleFactoryInstance" />
    <bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>
```

在调用对象时和 基于 构造方法创建对象一样，直接使用 applicationContext 对象 的 getBean 方法获取即可。

### 多个 applicationContext.xml 文件

假设有多个 applicationContext 文件，里面定义了重复的id，则后创建的会覆盖掉前面创建的，创建的顺序由配置文件的顺序决定。比如在下面代码中， 如果有两个 id 相同的bean。applicationContext2.xml 里面的bean 就会覆盖掉 applicationContext.xml 里面的bean

```java
// 如果有多个配置文件,后面的会覆盖掉前面的
String[] configLocations = new String[]{"classpath:applicationContext.xml","classpath:applicationContext2.xml"};
//创建 Spring IoC 容器, 并配置文件在容器中实例化对象
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
```
