Spring 容器在初始化一个 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 作用域,只需将
<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 属性有五个值,具体说明如下表。
环境搭建
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 异常。