文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

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配置的装配

在这里插入图片描述


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()

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标注控制器层(控制层)。

在这里插入图片描述


package annotation.dao;
import org.springframework.stereotype.Repository;
@Repository("testDao")

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
	
	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();
	}
}

总结

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯