# IOC-2

# 依赖注入

依赖注入,即为前面说的 DI(Dependency Injection)

依赖:指 Bean 对象的创建依赖于容器 。Bean 对象的依赖资源。

注入:指 Bean 对象所依赖的资源,由容器来设置和装配。

# 构造器注入

这个就需要你的实体类必须要有有参或者无参构造。

# 无参构造方法

1. 实体类

public class User {
   private String name;
   public User() {
       System.out.println("user无参构造方法");
  }
    public void setName(String name) {
        this.name = name;
    }
   public void show(){
       System.out.println("name="+ name );
  }
}

2. 编写 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="user" class="com.Meteor.pojo.User">
       <property name="name" value="zed"/>
   </bean>
</beans>

3. 测试

@Test
public void test(){
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   // 在执行 getBean 的时候,user 已经创建好了,通过无参构造
   User user = (User) context.getBean("user");
   // 调用对象的方法 .
   user.show();
}

# 有参构造方法

1. 实体类

public class User {
   private String name;
   public User(String name) {
       this.name = name;
       System.out.println("user有参构造方法");
  }
    public void setName(String name) {
        this.name = name;
    }
   public void show(){
       System.out.println("name="+ name );
  }
}

2.beans.xml

<!-- 第一种根据 index 参数下标设置 -->
<bean id="user" class="com.Meteor.pojo.User">
   <!-- index 指构造方法,下标从 0 开始 -->
   <constructor-arg index="0" value="zed"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="user" class="com.Meteor.pojo.User">
   <!-- name 指参数名 -->
   <constructor-arg name="name" value="Aki"/>
</bean>

然后感觉下面这个就很捞了

<!-- 第三种根据参数类型设置 -->
<bean id="user" class="com.Meteor.pojo.User">
   <constructor-arg type="java.lang.String" value="55open"/>
</bean>

3. 测试

@Test
public void test(){
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   User user = (User) context.getBean("user");
   user.show();
}

然后我们可以知道,实质上加载配置文件的时候,已经初始化了对象。看无参构造的控制台输出可以推测,看有参构造就可以直接看出了。

# set 注入

​ 要求被注入的属性,必须有 set 方法,set 方法的方法名由 set + 属性首字母大写 。实际上就是 idea 快捷键为你准备好的标准方法名字。

:::warning

如果你的对象类中同时有 set 方法和构造器方法,那么它会优先考虑构造器,因为 set 注入的本质就是调用默认的无参构造然后再 set 方法 set 参数。

:::

下图为同时使用了写了 set 方法和构造器方法导致的无法正常的使用 set 方法中常量注入。

所以这里一定要注意

:::info

以下是为了体验各种数据类型而设计的实体类

:::

public class Person {
    private String name;
    private Work work;
    private String[] hobbies;
    private List<String> books;
    private Map<String,String> certificates;
    private Set<String> collections;
    private String face;
    private Properties information;
    // 为了避免代码块太长省略了 set 方法部分。
    // 注意这里是没有构造器方法的
}
public class Work {
    private int money;
    private String name;
}

# 1. 常量注入

<bean id="person" class="com.Meteor.pojo.Person">
        <property name="name" value="韩金轮"/>
</bean>

# 2.Bean 注入

<bean id="work" class="com.Meteor.pojo.Work">
        <property name="name" value="cook"/>
        <property name="money" value="100000"/>
    </bean>
    <bean id="person" class="com.Meteor.pojo.Person">
        <property name="name" value="韩金轮"/>
</bean>

# 3. 数组注入

<bean id="person" class="com.Meteor.pojo.Person">
        <property name="name" value="韩金轮"/>
        <property name="work" ref="work"/>
        <property name="hobbies">
            <array>
                <value>肉蛋葱鸡</value>
                <value>盛酱喜鲤</value>
                <value>巨笼粧鸡</value>
            </array>
        </property>
</bean>

# 4.List 注入

<property name="books">
            <list>
                <value>青春修炼手册</value>
                <value>如何学好小学数学</value>
                <value>厨司的自我修养</value>
            </list>
</property>
<!-- 为了避免越来越长,后面就只写 property 了 -->

# 5.Map 注入

<property name="certificates">
            <map>
                <entry key="金牌讲师" value="很强"/>
                <entry key="金牌厨师" value="还就那个更强了"/>
            </map>
</property>

# 6. Set 注入

<property name="collections">
            <set>
                <value>皮燕子</value>
                <value>红皮鸭子</value>
            </set>
 </property>

# 7.Null 注入

<property name="face">
            <null/>
</property>

# 8.Properties 注入

<property name="information">
            <props>
                <prop key="age">33</prop>
                <prop key="sex"></prop>
            </props>
        </property>

# p 命名和 c 命名注入

实质上就是说清楚到底是什么注入方式,不然会发生刚才所说 set 与构造器冲突的错误。

# p 命名注入

p 命名空间注入:需要在头文件中加入约束文件

xmlns:p="http://www.springframework.org/schema/p"
 <!--P (属性: properties) 命名空间,属性依然要设置 set 方法 -->
 <bean id="user" class="com.Meteor.pojo.User" p:name="faker" p:age="18"/>

# c 命名注入

c 命名空间注入:同样需要在头文件中加入约束文件

导入约束 : xmlns:c="http://www.springframework.org/schema/c"
 <!--C (构造: Constructor) 命名空间,属性依然要设置 set 方法 -->
 <bean id="user" class="com.Meteor.pojo.User" c:name="Rin" c:age="18"/>

# Bean 的作用域

# singleton

bean 的默认作用域,在 Spring IoC 容器中只存在一个 Bean 实例,Bean 以单例方式存在。

<bean id="ServiceImpl" class="com.Meteor.service.ServiceImpl" scope="singleton">

# prototype

每次从容器中调用 bean 的时候,都返回一个新的实例,即为每次调用 getBean 的时候,相当于都执行了一次 new XXX ()

<bean id="ServiceImpl" class="com.Meteor.service.ServiceImpl" scope="prototype">
<!--or-->
<bean id="ServiceImpl" class="com.Meteor.service.ServiceImpl" singleton="false">

# request

每次 HTTP 请求都会创建一个新的 Bean,该作用域只适用于 WebApplicationContext 环境。

# session

同一个 HTTP Session 贡献一个 Bean,不同的 Session 使用不同 Bean,仅适用于 WebApplicationContext 环境。

# globalSession

一般用于 Portlet 应用环境,仅适用于 WebApplicationContext 环境。