首页>>后端>>Spring->Spring——bean作用域和自动装配

Spring——bean作用域和自动装配

时间:2023-11-29 本站 点击:0

Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。

ScopeDescriptionsingleton(常用)单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。prototype(常用)原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。request在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。session在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。

1、bean作用域

1、singleton 作用域

singleton 是 Spring 容器默认的作用域,当一个 Bean 的作用域为 singleton 时,Spring 容器中只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,就只会返回 Bean 的同一个实例。

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

<beanid="user"class="com.cheng.pojo.User"scope="singleton"/>

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true

结果为true,这说明 Spring 容器只创建了一个 User类的实例。由于 Spring 容器默认作用域是 singleton,如果不设置 scope="singleton",则其输出结果也将是一个实例。

2、prototype 作用域

使用 prototype 作用域的 Bean 会在每次请求该 Bean 时都会创建一个新的 Bean 实例。因此对需要保持会话状态的 Bean应该使用 prototype 作用域。

在 Spring 配置文件中,要将 Bean 定义为 prototype 作用域,只需将元素的 scope 属性值定义成 prototype,其示例代码如下所示:

<beanid="user2"class="com.cheng.pojo.User"c:name="万里"c:age="3"c:address-ref="address"scope="prototype"/>

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user2",User.class);Useruser1=context.getBean("user2",User.class);System.out.println(user==user1);//false

两次输出的结果并不相同,这说明在 prototype 作用域下,Spring 容器创建了两个不同的 Person 实例。

2、bean的自动装配

什么是自动装配:

自动装配是Spring满足bean依赖的一种方式

Spring容器可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。

要使用自动装配,就需要配置 <bean>元素的 autowire 属性。autowire 属性有五个值,具体说明如下表。

名称说明byName根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。byType根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配。constructor根据构造方法的参数的数据类型,进行 byType 模式的自动装配。autodetect如果发现默认的构造方法,则用 constructor 模式,否则用 byType 模式。no默认情况下,不使用自动装配,Bean 依赖必须通过 ref 元素定义。

环境搭建

packagecom.cheng.pojo;publicclassPerson{privateCatcat;privateDogdog;privateStringname;publicCatgetCat(){returncat;}publicvoidsetCat(Catcat){this.cat=cat;}publicDoggetDog(){returndog;}publicvoidsetDog(Dogdog){this.dog=dog;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}@OverridepublicStringtoString(){return"Person{"+"cat="+cat+",dog="+dog+",name='"+name+'\''+'}';}}

packagecom.cheng.pojo;publicclassDog{publicvoidshout(){System.out.println("wang~");}}

packagecom.cheng.pojo;publicclassCat{publicvoidshout(){System.out.println("miao~");}}

byName自动装配

byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的<bean>id,必须保证<bean>id全局唯一

<beanid="cat"class="com.cheng.pojo.Cat"/><beanid="dog"class="com.cheng.pojo.Dog"/><beanid="person"class="com.cheng.pojo.Person"autowire="byName"><propertyname="name"value="万里"/></bean>

byType自动装配

byType:会自动在容器上下文查找,和自己对象属性类型对应的<bean>,必须保证<bean>类型全局唯一

<beanid="cat"class="com.cheng.pojo.Cat"/><beanid="dog111"class="com.cheng.pojo.Dog"/><beanid="person"class="com.cheng.pojo.Person"autowire="byName"><propertyname="name"value="万里"/></bean>

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

Java 从 JDK 5.0 以后,提供了 Annotation(注解)功能,Spring 从2.5也提供了对 Annotation 技术的全面支持。

使用注解要导入的配置文件:

<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--开启注解的支持--><context:annotation-config/></beans>

常用的注解如下。

1)@Component

可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。

2)@Repository

用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

3)@Service

通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

4)@Controller

通常作用在控制层,用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

5)@Autowired

用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。直接在属性或者set方法上使用即可,如果在属性上使用了@Autowired,可以忽略该属性的set方法。

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true0

补充:

@Nullable 字段标记了这个注解,说明该字段可以为空。

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true1

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true2

6)@Qualifier

与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,当一个类型的Bean有多个实例名称时,实例名称由 @Qualifier 注解的参数指定。

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true3

@Qualifier的使用

ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Useruser=context.getBean("user",User.class);Useruser1=context.getBean("user",User.class);System.out.println(user==user1);//true4

7)@Resource

其作用与 Autowired 一样。其区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照 Bean 实例名称进行装配。

@Resource 中有两个重要属性:name 和 type。

Spring 将 name 属性解析为 Bean 实例名称,type 属性解析为 Bean 实例类型。如果指定 name 属性,则按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配。

如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/333.html