【Spring】Bean的作用域以及Bean的自动装配

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【Spring】Bean的作用域以及Bean的自动装配,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

闲话

周末又来咯~

一、Bean的作用域

关键字:scope

1、单例作用域(Spring的默认机制)—-singleton

当我们定义 Bean 且将其范围限定为单例时,Spring IOC 容器将只创建一个与之相关对象实例。此实例将存储在此类单例 Bean 的缓存中,后续所有对该命名 Bean 的请求和引用都将返回缓存的对象

如下图所示,我们左侧三个bean中对accountDao的引用,得到的都是右侧bean创建的对象
在这里插入图片描述
XML中配置如下

<bean id="user" class="com.decade.pojo.User" c:age="18" c:name="decade" scope="singleton"/>

2、原型作用域—-prototype

与单例模式不同的是,每次我们请求或者引用某个原型模式的bean时,它都会创建一个新的对象实例

如下图所示,我们左侧对accountDao这个bean的每一次引用,都会创建一个新的对象实例
在这里插入图片描述
XML中配置如下

<bean id="user" class="com.decade.pojo.User" c:age="18" c:name="decade" scope="prototype"/>

3、请求作用域—-request

Bean 的作用域为 HTTP 请求级别,每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境,当请求完成处理时,将丢弃作用域为请求的 Bean

XML配置如下

<bean id="loginAction" class="com.something.LoginAction" scope="request"/>

4、会话作用域—-session

作用域是HTTP Session级别的,Session中所有http请求共享同一个请求的bean实例,等到Session结束后就销毁bean

XML配置如下

<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

5、全局作用域—-application

限定一个Bean的作用域为ServletContext的生命周期,它是ServletContext级别的,作为常规的ServletContext属性

XML配置如下

<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

二、bean的自动装配

1、自动装配的理解

自动装配是Spring满足bean依赖的一种方式,Spring会在上下文中自动寻找,并自动给bean装配属性,我们不再需要对属性进行赋值

2、三种装配方式

1)在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="hello" class="com.decade.pojo.Hello">
        <property name="name" value="decade"/>
    </bean>
</beans>

2)在Java代码中显示配置
可以参考【Spring】使用JavaConfig实现配置

3)隐式的自动装配
自动装配分为2种装配方式:byName和byType

我们结合代码实例来理解一下
首先我们创建一个人的实体类,她有一个小猫

public class Cat {
    public void bark() {
        System.out.println("喵喵");
    }
}

public class People {
    private Cat cat;
    private String name;

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public String getName() {
        return name;
    }

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

然后我们在xml文件中注册这些对象
按照原来的配置方式,我们需要在bean定义时显式的装配属性cat

<?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="cat" class="com.decade.pojo.Cat"/>

    <bean id="people" class="com.decade.pojo.People">
        <property name="name" value="decade"/>
        <property name="cat" ref="cat"/>
    </bean>
</beans>

但是我们现在使用隐式自动装配之后,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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="cat" class="com.decade.pojo.Cat"/>

    <!-- 
        使用byName自动注入,需要确保引用的bean的id唯一、并且和我们的属性set方法去掉set后的名字相同
        如果上面的cat改为cat2,那么自动注入就找不到对象了
        使用byType自动注入,需要确保bean指向的的class类型和我们的属性的类型保持一致
        它需要确保引用的bean的类型全局唯一,如果有2个bean的class指向同一个类,那么使用byType就会出错
    -->
    <bean id="people" class="com.decade.pojo.People" autowire="byName">
        <property name="name" value="decade"/>
    </bean>
</beans>

最后我们写一个测试类来进行测试

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        Cat cat = people.getCat();
        cat.bark();
    }
}

运行结果如下
在这里插入图片描述

三、使用注解实现自动装配

1、使用注解前提

1)导入约束

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd

2)开启注解支持的配置

<context:annotation-config/>

整体配置如下

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
        
    <!--开启注解的支持 -->
    <context:annotation-config/>
</beans>

2、使用注解

1)@Autowired

  • @Autowired注解是Spring自己定义的,它默认是按照byType的方式实现自动注入

  • 默认情况下,required属性默认为true,它要求@AutoWried装配的对象必须要在XML中被定义,如果允许不定义,可以设置当前对象的required属性为false,或者加上@Nullable注解

样例代码如下

import org.springframework.beans.factory.annotation.Autowired;

public class People {

    @Autowired(required = false)
    private Dog dog;

    public Dog getDog() {
        return dog;
    }
}

为true时,如果在spring的ioc容器中找不到对象就会报错
在这里插入图片描述

  • 如果存在XML中定义了多个同类型的bean,我们可以使用@Qualifier注解指定使用哪一个bean

下面我们结合代码实例来进行理解,假设还是上面那个例子,我们的people对象有一只小猫和一只小狗,我们在beans.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"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

   <!--开启注解的支持 -->
   <context:annotation-config/>

   <bean id="cat1" class="com.decade.pojo.Cat"/>
   <bean id="cat2" class="com.decade.pojo.Cat"/>
   <bean id="dog1" class="com.decade.pojo.Dog"/>
   <bean id="dog2" class="com.decade.pojo.Dog"/>

   <bean id="people" class="com.decade.pojo.People"/>
</beans>

可以看到,在Spring上下文中,Dog类和Cat类都有2个bean,所以我们在People类中引用时,使用@Qualifier注解进行区分,就像这里,我们使用cat1这个bean的对象实例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.Nullable;

public class People {
    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;
    
    @Nullable
    private Dog dog;
    
    private String name;

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }

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

2)@Resource

  • @Resource注解是JDK自己定义的,它默认是按照byName的方式实现自动注入,但是它也支持byType的方式。如果name匹配不上(即bean的id),那么就会根据type进行匹配
  • 根据type进行匹配时,Spring上下文(即bean相关的XML)中只能存在一个该类型的bean(如果指定了type属性使用@Resource注入dog,那么就会报错)
  • 也可以同时指定了name和type属性,例如@Resource(name = “dog2”, type = Dog.class),那么就会去Spring上下文中找唯一的bean进行装配

这是我们的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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解的支持 -->
    <context:annotation-config/>

    <bean id="cat1" class="com.decade.pojo.Cat"/>
    <bean id="dog1" class="com.decade.pojo.Dog"/>
    <bean id="dog2" class="com.decade.pojo.Dog"/>

    <bean id="people" class="com.decade.pojo.People"/>
</beans>

这是我们在Java代码中使用@Resource注解实现自动装配

import javax.annotation.Resource;

public class People {
    @Resource
    private Cat cat;

    @Resource(name = "dog2")
    private Dog dog;

    private String name;

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }

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

如有错误,欢迎指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/136786.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!