Spring DI

学习自用



前言

Spring 是通过反射来实现注入的


一、什么是依赖注入?

Dependency Injection,是实现 Spring 控制反转思想的技术

在 Spring 中,组件之间的依赖关系由 Spring 容器(Ioc 容器)在运行期间决定。通俗的说,依赖注入是由容器动态的向某个对象提供它所需要的其他对象


依赖:对象(组件)和对象(组件)之间的关联关系,如业务层与持久层的关系,业务层调用持久层
注入:一种数据传递行为,通过注入行为来让对象和对象产生关系,分为以下两种方式

  • set 注入
  • 构造注入

1.1 目的

① 提升组件重用的频率
② 为系统搭建一个灵活、可扩展的平台

1.2 结果

通过赖注入机制,我们只需要通过简单的配置,无需任何代码就可指定目标需要的资源,便可完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现,降低耦合度。

1.3 理解关键

谁依赖于谁

应用程序依赖于 Spring IOC 容器,即使用者依赖于方法调用方,如 service 对象依赖于 dao 对象

为什么需要依赖

应用程序需要 IoC 容器来提供目标对象所需要的外部资源

谁注入谁

IoC容器注入应用程序中的某个对象,是应用程序中注入的目标对象所依赖的对象,即Spring 给使用者注入依赖对象

注入了什么

注入目标对象所需要的外部资源(包括对象、资源、常量数据)

二、Bean 管理

使用< bean />标签

<bean id="" class=""  name=""> </bean>

2.1 基本属性

1)id

  • bean 的唯一标识,具有唯一性
  • 命名规范与 Java 命名规范一致

2)name

  • 也是bean的标识,但与 id 不同,不做唯一要求和命名规范
  • 如果没有设置name 只设置了 id,那么 name 的值为id的值
  • 如果设置name 没有设置 id,也能根据 name 找到对应的 bean
  • 如果都设置了,那么只要是 id 或者 name 的值就能知道对应的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.xsd">

    <bean id="user1" name="user" class="com.fs.pojo.User"> </bean>
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user", User.class);
User user1 = context.getBean("user1", User.class);
System.out.println(user == user1);  // true
  • 如果都没有设置,则以该 Bean 对应的全限定类名 + #下标给 Bean 标识,下标从 0 开始
    在这里插入图片描述

3)scope

  • Bean 作用域
  • 默认为单例(singleton):即通过 getBean() 获取这个Bean,不管是获取几次,都是同一个 Bean 实例。对象在Spring容器创建时创建
// Spring容器创建
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml")
  • 多例(prototype):每次都是获取的一个全新的 Bean 实例,各不相同。此时对象是在需要用的时候创建,即调用 getBean() 方法时才会创建

2.2 别名

使用 < alias /> 标签,为对应 Bean 对象取别名

<bean class="com.fs.pojo.User" name="user" id="user1">
    <property name="monies">
        <list>
            <ref bean="money3" />
        </list>
    </property>
</bean>

<alias name="user" alias="xxx"/>
  • < alias /> 的 name 属性可以是 < bean /> 中的 id 属性的值,也可以是 < bean /> 中的 name 属性的值
  • < alias /> 的 alias 为给对应 < bean /> 取的别名

2.3 生命周期

  • init-method
    • Bean 初始化方法名
    • 用处:数据初始化,如创建连接池
  • destory-method
    • Bean 销毁之前的方法名
    • 作用:释放资源,如关闭连接池中的连接对象

2.4 实例化

静态工厂方法

Spring 不管理静态工厂,通过静态工厂方法创建对象

创建一个工厂类,提供一个创建对象的静态方法

/**
 * 产生User对象的静态工厂
 */
public class UserStaticFactory {
    /**
     * 静态工厂方法
     * @return User
     */
    public static User createUser(){
        System.out.println("静态工厂创建user...");
        return new User();
    }
}

在配置文件中创建对象

<bean id="user3" class="com.fs.factory.UserStaticFactory" factory-method="createUser"> </bean>

注意

  • id:创建的目标对象的标识
  • class:是静态工厂全限定类名,不是目标对象的
  • factory-method:工厂创建对象的静态方法

实例工厂方法

Spring 管理实例工厂,使用实例工厂方法创建对象

创建一个工厂类,提供一个创建对象的非静态方法

public class UserInstanceFactory {
    public User createUser(){
        System.out.println("实例工厂创建user...");
        return new User();
    }
}

配置文件注入实例工厂对象,并创建目标对象

<!-- 把实例工厂对象交给Spring管理-->
<bean id="userInstanceFactory" class="com.fs.factory.UserInstanceFactory"> </bean>

<!-- 创建目标对象 -->
<bean id="user4" class="com.fs.pojo.User" factory-bean="userInstanceFactory" factory-method="createUser"> </bean>

注意
- factory-bean工厂对象的bean的id
- factory-method:调用创建的对象方法

构造方法

Bean 实例化默认方式,调用目标类的构造方法创建对象

<bean id="userDao" class="com.fs.dao.impl.UserDaoImpl" init-method="init" destroy-method="close"></bean>

2.5 自动装配

使用autowire属性

spring 根据 Bean 的依赖,自动给属性注入值

通俗点说,就是开启了autowire属性之后,一个bean依赖的其他bean不再需要手动写,Spring 会根据自动装配的模式找到配置文件中的对应的目标 bean 对象,并自动注入

  • autowrie
    • 默认不开启
    • 模式
      • 根据类型:byType, 如果有多个相同的类型,会抛异常
      • 根据set方法之后的字符名字:byName
public class Person {
    private Money m;

    public void setMoney4(Money m) {
        this.m = m;
    }
    public Money getM() {
        return m;
    }

    @Override
    public String toString() {
        return "Person{" +
                "m=" + m +
                '}';
    }
}
<bean id="money4" class="com.fs.pojo.Money">
    <property name="num" value="100"/>
</bean>
<bean id="person" class="com.fs.pojo.Person" autowire="byName"> </bean>

三、构造注入

通过< constructor-arg >标签进行构造器参数注入
标签属性说明
name:构造方法参数名
type:属性类型
index:参数索引(从0开始)
ref:当属性是对象时,使用 ref 来引用该对象 bean 的值

// lombok注解:Set、Get、toString方法等
@Data
// lombok注解:有参构造
@AllArgsConstructor
// lombok注解:无参构造
@NoArgsConstructor
public class User {
    private String name;
    private Dog dog;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog {
    private String name;
}

3.1 使用 name + value / ref

<?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="dog" class="com.fs.pojo.Dog">
    <constructor-arg name="name" value="旺财"/>
  </bean>

  <bean id="user" class="com.fs.pojo.User">
    <constructor-arg name="name" value="张三"/>
    <constructor-arg name="dog" ref="dog"/>
  </bean>
</beans>

3.2 使用 index + value /ref

<?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="dog" class="com.fs.pojo.Dog">
        <constructor-arg name="name" value="旺财"/>
    </bean>

    <bean id="user" class="com.fs.pojo.User">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" ref="dog"/>
    </bean>
</beans>

3.3 使用 value /ref

会自动进行类型判断

<?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="dog" class="com.fs.pojo.Dog">
        <constructor-arg name="name" value="旺财"/>
    </bean>

    <bean id="user" class="com.fs.pojo.User">
        <constructor-arg value="张三"/>
        <constructor-arg ref="dog"/>
    </bean>
</beans>

这种方式需要注意

  • 当注入的对象有相同类型的属性时,注入的值会根据配置文件中的顺序进行注入
  • 反之,若注入的对象的属性不存在相同类型时,没有顺序要求,Spring 会自动对属性进行类型判断

四、Set 注入

set 注入基于属性的 set 方法实现,底层通过反射机制调用属性对应的set方法进行属性赋值

  • 属性是基本数据类型,使用 value 注入值
  • 属性是其他 bean 对象时,使用 ref 注入值
<bean id="user" class="com.fs.pojo.User">
    <property name="sex" value=""/>
    <property name="money" ref="money1"/>
</bean>

4.1 < p />

可以使用 < P /> 命名空间进行简化 set 注入

注意:需要在配置文件头部加入p的约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  
       <!-- 需要在配置文件头部加入p的约束 -->
       xmlns:p="http://www.springframework.org/schema/p"
  
       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.fs.pojo.User" p:sex="" p:money-ref="money1">
          <!--<property name="sex" value="男"/>-->
          <!--<property name="money" ref="money1"/>-->
      </bean>
</beans>

4.2 数组属性

语法
< bean id=“” class=“”>
 < property name=“属性名”>
   < array >
     < value >值</ value >
   < /array >
 < /property>
< /bean>

<bean id="user" class="com.fs.pojo.User">
  <property name="属性名">
    <array>
      <value>张三</value>
      <value>李四</value>
    </array>
  </propery>
</bean>

4.3 List 属性

元素有序,即按照赋值的顺序注入到 List 集合中

语法
< bean id=“” class=“”>
 < property name=“属性名”>
   < list >
     < value >值</ value >
   < /list >
 < /property>
< /bean>

当 List 的元素是普通类型

<bean id="user" class="com.fs.pojo.User">
  <property name="属性名">
    <list>
      <value>张三</value>
      <value>李四</value>
    </list>
  </propery>
</bean>

当 List 的元素是其他 bean

<bean id="money1" class="com.fs.pojo.Money">
    <property name="num" value="100"/>
</bean>
<bean id="money2" class="com.fs.pojo.Money">
    <property name="num" value="200"/>
</bean>

<bean class="com.fs.pojo.User">
    <property name="monies">
        <list>
            <ref bean="money1" />
            <ref bean="money2" />
        </list>
    </property>
</bean>

4.4 Set 集合属性

自动去重,且无序排列

语法
< bean id=“” class=“”>
 < property name=“属性名”>
   < set >
     < value >值</ value >
   < /set >
 < /property>
< /bean>

<bean id="user" class="com.fs.pojo.User">
  <property name="属性名">
    <set>
      <value>张三</value>
      <value>李四</value>
    </set>
  </propery>
</bean>

4.4 Map 属性

语法
< bean id=“” class=“”>
 < property name=“属性名”>
   < map >
     < entry key=“” value=“” />
   < /map >
 < /property>
< /bean>

<bean id="user" class="com.fs.pojo.User">
  <property name="属性名">
    <map>
      <entry key="zs" value="张三"></entry>
    </map>
  </propery>
</bean>

4.5 Properties 属性

继承自 HashMap,key 与 value 都是 String 类型

语法
< bean id=“” class=“”>
 < property name=“属性名”>
   < props >
     < prop key=“zs” value=“张三” />
   < /props >
 < /property>
< /bean>

<bean id="user" class="com.fs.pojo.User">
  <property name="属性名">
    <props>
      <prop key="zs" value="张三"></prop>
    </props>
  </propery>
</bean>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值