欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Bean的作用域,生命周期和注解

程序员文章站 2022-03-06 14:47:09
目录bean的作用域singleton作用域bean的生命周期1.创建bean的实现类2.配置bean3.测试生命周期bean的装配方式基于xml配置的装配基于注解的装配1.@component2.@...

bean的作用域

Java Bean的作用域,生命周期和注解

singleton作用域

当将bean的scope设置为singleton时,spring ioc容器仅生成和管理一个bean实例(单例)。使用id或name获取bean实例时,ioc容器将返回共享的bean实例。

由于singleton是scope(范围)的默认方式,因此有两种方式将bean的scope设置为singleton。配置文件示例代码如下:

<bean id="constructorinstance" class="instance.beanclass"/>
或
<bean id="constructorinstance" class="instance.beanclass" scope="singleton"/>

测试singleton作用域,代码如下:

//初始化spring容器applicationcontext,加载配置文件
applicationcontext appcon = new classpathxmlapplicationcontext("applicationcontext.xml");
//测试构造方法实例化bean
beanclass b1 = (beanclass)appcon.getbean("constructorinstance");
system.out.println(b1);
beanclass b2 = (beanclass)appcon.getbean("constructorinstance");
system.out.println(b2);	

prototype作用域

当bean的scope设置为prototype(原型)时,spring ioc容器将为每次请求创建一个新的实例。如果将3.3.1中bean的配置修改如下:

<bean id="constructorinstance" class="instance.beanclass" scope="prototype"/>

bean的生命周期

bean的生命周期整个过程如下:

1.根据bean的配置情况,实例化一个bean。

2.根据spring上下文对实例化的bean进行依赖注入,即对bean的属性进行初始化。

3.如果bean实现了beannameaware接口,将调用它实现的setbeanname(string beanid)方法,此处参数传递的是spring配置文件中bean的id。

4.如果bean实现了beanfactoryaware接口,将调用它实现的setbeanfactory()方法,此处参数传递的是当前spring工厂实例的引用。

5.如果bean实现了applicationcontextaware接口,将调用它实现的setapplicationcontext(applicationcontext)方法,此处参数传递的是spring上下文实例的引用。

6.如果bean关联了beanpostprocessor接口,将调用预初始化方法postprocessbeforeinitialization(object obj, string s)对bean进行操作。

7.如果bean实现了initializingbean接口,将调用afterpropertiesset()方法。

8.如果bean在spring配置文件中配置了init-method属性,将自动调用其配置的初始化方法。

9.如果bean关联了beanpostprocessor接口,将调用postprocessafterinitialization(object obj, string s)方法,由于是在bean初始化结束时调用after方法,也可用于内存或缓存技术。

以上工作(1至9)完成以后就可以使用该bean,由于该bean的作用域是singleton,所以调用的是同一个bean实例。

10.当bean不再需要时,将经过销毁阶段,如果bean实现了disposablebean接口,将调用其实现的destroy方法将spring中的bean销毁。

11.如果在配置文件中通过destroy-method属性指定了bean的销毁方法,将调用其配置的销毁方法进行销毁。

1.创建bean的实现类

package life;
public class beanlife {
	public void initmyself() {
		system.out.println(this.getclass().getname() + "执行自定义的初始化方法");
	}
	public void destroymyself() {
		system.out.println(this.getclass().getname() +"执行自定义的销毁方法");
	}
}

2.配置bean

在spring配置文件中,使用实现类beanlife配置一个id为beanlife的bean。具体代码如下:

<!-- 配置bean,使用init-method属性指定初始化方法,使用 destroy-method属性指定销毁方法-->
<bean id="beanlife" class="life.beanlife" init-method="initmyself" destroy-method="destroymyself"/>

3.测试生命周期

在ch3应用的test包中,创建测试类testlife,具体代码如下:

//初始化spring容器,加载配置文件
//为了方便演示销毁方法的执行,这里使用classpathxmlapplicationcontext
//实现类声明容器
classpathxmlapplicationcontext ctx = 
new classpathxmlapplicationcontext("applicationcontext.xml");
system.out.println("获得对象前");
beanlife blife = (beanlife)ctx.getbean("beanlife");
system.out.println("获得对象后" + blife);
ctx.close();//关闭容器,销毁bean对象

bean的装配方式

bean的装配可以理解为将bean依赖注入到spring容器中,bean的装配方式即bean依赖注入的方式。spring容器支持基于xml配置的装配、基于注解的装配以及自动装配等多种装配方式。本节将主要讲解基于xml配置的装配和基于注解的装配。

基于xml配置的装配

Java Bean的作用域,生命周期和注解

package assemble;
import java.util.list;
import java.util.map;
import java.util.set;
public class complexuser {
	private string uname;
	private list<string> hobbylist;
	private map<string,string> residencemap;//map存储键值对
	private set<string> aliasset;
	private string[] array;
	//使用构造方法注入,需要提供带参数的构造方法
	public complexuser(string uname, list<string> hobbylist, map<string, string> residencemap, set<string> aliasset,
			string[] array) {
		super();
		this.uname = uname;
		this.hobbylist = hobbylist;
		this.residencemap = residencemap;
		this.aliasset = aliasset;
		this.array = array;
	}
	//使用setter方法注入,提供默认无参数的构造方法,并为注入的属性提供setter方法
	public complexuser() {
		super();
	}
	public void setuname(string uname) {
		this.uname = uname;
	}
	public void sethobbylist(list<string> hobbylist) {
		this.hobbylist = hobbylist;
	}
	public void setresidencemap(map<string, string> residencemap) {
		this.residencemap = residencemap;
	}
	public void setaliasset(set<string> aliasset) {
		this.aliasset = aliasset;
	}
	public void setarray(string[] array) {
		this.array = array;
	}
	@override
	public string tostring() {
		return "uname="+uname+";hobbylist="+hobbylist+";residencemap="+residencemap+";alisaset="+aliasset+";array="+array;
	}
	
}
<!-- 使用构造方法注入方式装配complexuser实例user1 -->
   		<bean id="user1" class="assemble.complexuser" >
   			<constructor-arg index="0" value="chenheng1" />
   			<constructor-arg index="1">
   				<list>
   					<value>唱歌</value>
   					<value>跳舞</value>
   					<value>篮球</value>
   				</list>
   			</constructor-arg>
   			<constructor-arg index="2">
   				<map>
   					<entry key="dalian" value="大连" />
   					<entry key="beijing" value="北京" />
   					<entry key="shanghai" value="上海" />
   				</map>
   			</constructor-arg>
   			<constructor-arg index="3">
   				<set>
   					<value>陈恒100</value>
   					<value>陈恒101</value>
   					<value>陈恒102</value>
   				</set>
   			</constructor-arg>
   			<constructor-arg index="4">
   				<array>
   					<value>aaaaa</value>
   					<value>bbbbb</value>
   				</array>
   			</constructor-arg>
   		</bean>  			      
		<!-- 使用setter方法注入方式装配complexuser实例user2 -->
		<bean id="user2" class="assemble.complexuser" >	
			<property name="uname" value="chenheng2"></property>
			<property name="hobbylist">
				<list>
					<value>看书</value>
					<value>学习spring</value>
				</list>
			</property>
			<property name="residencemap">
				<map>
					<entry key="shenzhen" value="深圳"></entry>
					<entry key="guangzhou" value="广州"></entry>
					<entry key="tianjin" value="天津"></entry>
				</map>
			</property>
			<property name="aliasset">
				<set>
					<value>陈恒103</value>
					<value>陈恒104</value>
					<value>陈恒105</value>
				</set>
			</property>
			<property name="array">
				<array>
					<value>ccccc</value>
					<value>ddddd</value>
				</array>
			</property>
		</bean>
package test;
import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
import assemble.complexuser;
public class testassemble {
	public static void main(string[] args) {
		classpathxmlapplicationcontext appcon=new classpathxmlapplicationcontext("applicationcontext.xml");
		complexuser u1=(complexuser) appcon.getbean("user1");
		//构造方法装配测试
		system.out.println(u1);
		//setter方法装配测试
		complexuser u2=(complexuser) appcon.getbean("user2");
		system.out.println(u2);
		appcon.close();
	}
}

基于注解的装配

1.@component

该注解是一个泛化的概念,仅仅表示一个组件对象(bean),可以作用在任何层次上。

(1)创建bean的实现类

package annotation;
import org.springframework.beans.factory.annotation.value;
import org.springframework.stereotype.component;
@component()
/**相当于@component("annotationuser")或@component(value = "annotationuser"),annotationuser为bean的id,默认为首字母小写的类名**/
public class annotationuser {
	@value("chenheng")//只注入了简单的值,复杂值的注入目前使用该方式还解决不了
	private string uname;
	public string getuname() {
		return uname;
	}
	public void setuname(string uname) {
		this.uname = uname;
	}
	@override
	public string tostring() {
		return "uname="+uname;
	}
}

(2)配置注解

现在有了bean的实现类,但还不能进行测试,因为spring容器并不知道去哪里扫描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"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemalocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd">
         <!-- 使用context命名空间,通过spring扫描指定包下所有bean的实现类,进行注解解析 -->
         <context:component-scan base-package="annotation" />
</beans>

(3)测试bean实例

package test;

import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
import annotation.annotationuser;
public class testannoation {
	public static void main(string[] args) {
		applicationcontext appcon=new classpathxmlapplicationcontext("annotationcontext.xml");
		annotationuser au=(annotationuser) appcon.getbean("annotationuser");
		system.out.println(au.getuname());
	}
}

2.@repository

该注解用于将数据访问层(dao)的类标识为bean,即注解数据访问层bean,其功能与@component()相同。

3.@service

该注解用于标注一个业务逻辑组件类(service层),其功能与@component()相同。

4.@controller

该注解用于标注一个控制器组件类(spring mvc的controller),其功能与@component()相同。

5.@autowired

该注解可以对类成员变量、方法及构造方法进行标注,完成自动装配的工作。 通过 @autowired的使用来消除setter 和getter方法。默认按照bean的类型进行装配。

6.@resource

该注解与@autowired功能一样。区别在于,该注解默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;而@autowired默认按照bean的类型进行装配,如果想按照名称来装配注入,则需要结合@qualifier注解一起使用。

@resource注解有两个属性:name和type。name属性指定bean实例名称,即按照名称来装配注入;type属性指定bean类型,即按照bean的类型进行装配。

7.@qualifier

该注解与@autowired注解配合使用。当@autowired注解需要按照名称来装配注入,则需要结合该注解一起使用,bean的实例名称由@qualifier注解的参数指定。

上面几个注解中,虽然@repository、@service和 @controller等注解的功能与@component()相同,但为了使标注类的用途更加清晰(层次化),在实际开发中推荐使用@repository标注数据访问层(dao层)、使用@service标注业务逻辑层(service层)以及使用@controller标注控制器层(控制层)。

Java Bean的作用域,生命周期和注解

package annotation.dao;
import org.springframework.stereotype.repository;
@repository("testdao")
/**相当于@repository,但如果在service层使用@resource(name="testdao")的话,testddao不能省略**/
public class testdaoimpl implements testdao {
	@override
	public void save() {
		// todo auto-generated method stub
		system.out.println("testdao save");
	}
}
package annotation.service;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.service;
import annotation.dao.testdao;
import jakarta.annotation.resource;
@service("testservice")
public class testserviceimpl implements testservice {
	@autowired
	/**相当于@autowired.@autowired默认按照bean类型装配**/
	private testdao testdao;
	@override
	public void save() {
		// todo auto-generated method stub
		testdao.save();
		system.out.println("testservice save");
	}
}
package annotation.controller;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.controller;
import annotation.service.testservice;
@controller("testcontroller")
public class testcontrollerimpl {
	@autowired
	private testservice testservice;
	public void save() {
		// todo auto-generated method stub
		testservice.save();
		system.out.println("testcontroller save");
	}
}
<?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 
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd">
         <!-- 使用context命名空间,通过spring扫描指定包下所有bean的实现类,进行注解解析 -->
         <context:component-scan base-package="annotation" />
</beans>
package test;
import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
import annotation.controller.testcontrollerimpl;
public class testmoreannotation {
	public static void main(string[] args) {
		applicationcontext appcon=new classpathxmlapplicationcontext("annotationcontext.xml");
		testcontrollerimpl testc=(testcontrollerimpl) appcon.getbean("testcontroller");
		testc.save();
	}
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!