Spring(6)依赖注入

6.依赖注入

6.1 构造器注入

  可以看Spring(4)IOC的创建方式

6.2 Set方式注入【重点】

  依赖注入:Set注入!

   依赖:bean对象的创建依赖于容器!

   注入:bean对象中的所有属性,由容器来注入!

 

  6.2.1 环境搭建

  复杂类型搭建(ref 主要实现引用类型)

复制代码
public class Address {

    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
复制代码

  6.2.2 真实测试对象

复制代码
public class Student {

    private String name;
    private Address address;        //引用类型
    private String[] books;         //数组
    private List<String> hobbies;   //List集合
    private Set<String> games;      //Set集合
    private String wife;
    private Properties info;        //properties

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }
}
复制代码

  6.3.3 Spring文件

复制代码
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.luo.pojo.Address">
        <property name="address" value="北京"></property>
    </bean>

    <bean id="student" class="com.luo.pojo.Student">
        <property name="name" value="十三"></property>
        <!-- bean注入-->
        <property name="address" ref="address"></property>
        <!--数组注入 -->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>三国演义</value>
                <value>西游记</value>
                <value>水浒传</value>
            </array>
        </property>
        <!--list -->
        <property name="hobbies">
            <list>
                <value>敲代码</value>
                <value>看书</value>
                <value>踢足球</value>
            </list>
        </property>
        <!-- map- -->
        <property name="card">
            <map>
                <entry key="省份证" value="12345678897897897"></entry>
                <entry key="银行卡" value="54678646548798545"></entry>
            </map>
        </property>
        <!--set -->
        <property name="games">
            <set>
                <value>王者荣耀</value>
                <value>实况足球</value>
            </set>
        </property>
        <!--null -->
        <property name="wife">
            <null></null>
        </property>
        <!-- property-->
        <property name="info">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>

</beans>
复制代码

  6.3.4 测试

复制代码
 public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student =(Student) context.getBean("student");
        System.out.println(student.getName());
        System.out.println(student.getAddress());
        String[] books = student.getBooks();
        for (String book:books) {
            System.out.print(book+"\t");
        }
        System.out.println("\n"+"==============================");
        List<String> hobbies = student.getHobbies();
        for (String hobby:hobbies) {
            System.out.print(hobby+"\t");
        }
        System.out.println("\n"+"==============================");
        Map<String, String> card = student.getCard();
        System.out.println(card.get("省份证"));
        System.out.println(card.get("银行卡"));
        System.out.println("====================================");

        Set<String> games = student.getGames();
        for (String game:games) {
            System.out.println(game);
        }
        System.out.println("====================================");
        Properties info = student.getInfo();
        System.out.println(info.getProperty("username"));
        System.out.println(info.getProperty("password"));
    }
复制代码

 

 

 6.3 p命名和c命名


复制代码
  在使用p命名和c命名之前我们需要导入xml约束,他俩是不能直接使用的。

  p:命名约束 xmlns:p="http://www.springframework.org/schema/p"

  c:命名约束 xmlns:c="http://www.springframework.org/schema/c"
复制代码
  p 命名空间是 setter 方式属性注入的一种快捷实现方式。通过它,我们能够以 bean 属性的形式实现 setter 方式的属性注入,而不再使用嵌套的 <property> 元素,
以实现简化 Spring 的 XML 配置的目的。

  使用 p 命名空间注入依赖时,必须注意以下 3 点:
    •   Java 类中必须有 setter 方法;
    •   Java 类中必须有无参构造器(类中不包含任何带参构造函数的情况,无参构造函数默认存在);
    •   在使用 p 命名空间实现属性注入前,XML 配置的 <beans> 元素内必须先导入 p 命名空间的 XML 约束。
 下面实例展示
  用户类:
复制代码
public class User {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
复制代码

    spring文件

复制代码
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="user" class="com.luo.pojo.User" p:name="学生"></bean>
</beans>
复制代码

 


c 命名空间注入

c 命名空间是构造函数注入的一种快捷实现方式。通过它,我们能够以 <bean> 属性的形式实现构造函数方式的属性注入,而不再使用嵌套的 <constructor-arg> 元素,
以实现简化 Spring 的 XML 配置的目的。

首先我们需要在配置文件的 <beans> 元素中导入以下 XML 约束。
  1. xmlns:c="http://www.springframework.org/schema/c"
在导入 XML 约束后,我们就能通过以下形式实现属性注入。

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

使用 c 命名空间注入依赖时,必须注意以下 2 点:
    • Java 类中必须包含对应的带参构造器;
    • 在使用 c 命名空间实现属性注入前,XML 配置的 <beans> 元素内必须先导入 c 命名空间的 XML 约束。
 

  我们修改User类加入有参构造

复制代码
public class User {

    private String name;

    public User(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
复制代码

 

  Spring文件

复制代码
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <!--   <bean id="user" class="com.luo.pojo.User" p:name="学生"></bean>-->
    <bean id="user2" class="com.luo.pojo.User" c:name="学生"></bean>
</beans>
复制代码

 6.4 bean的作用域

默认情况下,所有的 Spring Bean 都是单例的,也就是说在整个 Spring 应用中, Bean 的实例只有一个。

我们可以在 <bean> 元素中添加 scope 属性来配置 Spring Bean 的作用范围。例如,如果每次获取 Bean 时,都需要一个新的 Bean 实例,那么应该将 Bean 的 scope 属性定义为 prototype,如果 Spring 需要每次都返回一个相同的 Bean 实例,则应将 Bean 的 scope 属性定义为 singleton。

Spring 5 共提供了 6 种 scope 作用域,如下表。 

作用范围描述
singleton 默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例
prototype 原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个新的 Bean 实例。
request 每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。
session 同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session 内有效。
application 同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。

与 singleton 类似,但 singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而一个 Web 应用中可能会存在多个 IoC 容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。
websocket websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效。

注意:在以上 6 种 Bean 作用域中,除了 singleton 和 prototype 可以直接在常规的 Spring IoC 容器(例如 ClassPathXmlApplicationContext)中使用外,剩下的都只能在基于 Web 的 ApplicationContext 实现(例如 XmlWebApplicationContext)中才能使用,否则就会抛出一个 IllegalStateException 的异常。

 

singleton

singleton 是 Spring 容器默认的作用域。当 Bean 的作用域为 singleton 时,Spring IoC 容器中只会存在一个共享的 Bean 实例。这个 Bean 实例将存储在高速缓存中,所有对于这个 Bean 的请求和引用,只要 id 与这个 Bean 定义相匹配,都会返回这个缓存中的对象实例。

如果一个 Bean 定义的作用域为 singleton ,那么这个 Bean 就被称为 singleton bean。在 Spring IoC 容器中,singleton bean 是 Bean 的默认创建方式,可以更好地重用对象,节省重复创建对象的开销。

在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性,将 Bean 的作用域定义成 singleton,其配置方式如下所示:

<bean id="..." class="..." scope="singleton"/>

我们修改之前userBeans.xml中的bean的配置,在后面加入作用域

 <bean id="user" class="com.luo.pojo.User" c:name="学生" scope="singleton"></bean>

测试可以发现单例模式,在Spring容器中只有一个实例

 

 

 

 

prototype

如果一个 Bean 定义的作用域为 prototype,那么这个 Bean 就被称为 prototype bean。对于 prototype bean 来说,Spring 容器会在每次请求该 Bean 时,都创建一个新的 Bean 实例。

从某种意义上说,Spring  IoC 容器对于 prototype bean 的作用就相当于 Java 的 new 操作符。它只负责 Bean 的创建,至于后续的生命周期管理则都是由客户端代码完成的,详情请参看《Spring Bean 生命周期》。

在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性将 Bean 的作用域定义成 prototype,其配置方式如下所示:

<bean id="..." class="..." scope="prototype"/>

我们修改之前userBeans.xml中的bean的配置,在后面加入作用域

 <bean id="user" class="com.luo.pojo.User" c:name="学生" scope="prototype"></bean>

测试方现原型模式, Spring 容器获取 Bean 时,容器都会创建一个新的 Bean 实例。

 

posted @   十三加油哦  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示