【Spring】介绍一下 Spring 的 xml 标签以及 Bean 的常用配置

发布于:2024-12-06 ⋅ 阅读:(130) ⋅ 点赞:(0)

配置标签

Spring 的 xml 标签大体上分为两类,一种是默认标签,一种是自定义标签

默认标签:就是不用额外导入其他命名空间约束的标签,例如 <bean> 标签

自定义标签:就是需要额外引入其他命名空间约束,并通过前缀引用的标签,例如 <context:propert-placeholder/> 标签

标签 作用
<beans> 一般作为 xml 配置根标签,其他标签都是该标签的子标签
<bean> Bean的配置标签,上面已经详解了,此处不再阐述
<import> 外部资源导入标签
<alias> 指定Bean的别名标签,使用较少

<beans>标签

除了经常用的做为根标签外,还可以嵌套在根标签内,使用profile属性切换开发环境

<!-- 配置测试环境下,需要加载的Bean实例 -->
<beans profile="test"></beans>
<!-- 配置开发环境下,需要加载的Bean实例 -->
<beans profile="dev"></beans>

可以使用以下两种方式指定被激活的环境:

  • 使用命令行动态参数,虚拟机参数位置加载 -Dspring.profiles.active=test
  • 使用代码的方式设置环境变量 System.setProperty("spring.profiles.active","test")

<import>标签

用于导入其他配置文件,项目变大后,就会导致一个配置文件内容过多,可以将一个配置文件根据业务某块进行拆分,拆分后,最终通过<import>标签导入到一个主配置文件中,项目加载主配置文件就连同<import> 导入的文件一并加载了

<!--导入用户模块配置文件-->
<import resource="classpath:UserModuleApplicationContext.xml"/>
<!--导入商品模块配置文件-->
<import resource="classpath:ProductModuleApplicationContext.xml"/>

<alias> 标签

为某个Bean添加别名,与在<bean> 标签上使用name属性添加别名的方式一样

<!--配置UserService-->
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<!--指定别名-->
<alias name="userService" alias="xxx"/>
<alias name="userService" alias="yyy"/>

自定义标签

Spring的自定义标签需要引入外部的命名空间,并为外部的命名空间指定前缀,使用 <前缀:标签> 形式的标签,称之为自定义标签,自定义标签的解析流程也是 Spring xml扩展点方式之一。(引入命名空间和文件映射地址)

<!--默认标签-->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!--自定义标签-->
<context:property-placeholder/>
<mvc:annotation-driven/>
<dubbo:application name="application"/>

Bean

Bean 就是由 Spring IoC 容器实例化、组装和管理的对象。Spring 通过配置文件(如XML文件)或注解来定义 Bean,并利用这些信息来创建和管理应用程序中的对象及其依赖关系。定义方式:

  • XML配置:在XML配置文件中使用 <bean> 标签来定义一个Bean。
  • Java配置:基于Java的配置方式,即通过 @Configuration 类配合 @Bean 注解来定义Bean。

Bean 常用配置

Xml配置方式 功能描述
<bean id=“” class=“”> Bean的id和全限定名配置
<bean name=“”> 通过name设置Bean的别名,通过别名也能直接获取到Bean实例
<bean scope=“”> Bean的作用范围,BeanFactory作为容器时取值singleton和prototype
<bean lazy-init=“”> Bean的实例化时机,是否延迟加载。BeanFactory作为容器时无效
<bean init-method=“”> Bean实例化后自动执行的初始化方法,method指定方法名
<bean destroy-method=“”> Bean实例销毁前的方法,method指定方法名
<bean autowire=“byType”> 设置自动注入模式,常用的有按照类型byType,按照名字byName
<bean factory-bean=“” factory-method=“”/> 指定哪个工厂Bean的哪个方法完成Bean的创建

Bean 作用域

定义了 Spring 容器如何创建和管理 Bean 的实例。Spring 提供了多种作用域来控制不同场景下的对象生命周期。

作用域 说明
singleton 默认值。Spring以单例模式创建Bean的实例,即容器中该Bean的实例只有一个
prototype 每次从容器中获取Bean时,都会创建一个新的实例
request 用于Web应用环境,针对每次HTTP请求都会创建一个实例
session 用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
global session 仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session
<bean id="user" class="cn.hz.pojo.User" scope="singleton"/>
<bean id="user" class="cn.hz.pojo.User" scope="prototype"/>

在这里插入图片描述

默认情况下,单纯的Spring环境Bean的作用范围有两个

singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;

prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。

使用 @Scope("prototype") 注解指定 Bean 的作用域

@Scope("prototype") 
@Service("userService") 
public class UserServiceImpl implements UserService {
    // 省略其他代码
}

Bean 实例化流程

Spring 容器在进行初始化时,会将 xml 配置的 <bean> 的信息封装成一个 BeanDefinition 对象,所有的 BeanDefinition 存储到一个名为 beanDefinitionMap 的 Map 集合中去,Spring 框架在对该 Map 进行遍历,使用反射创建 Bean 实例对象,创建好的 Bean 对象存储在一个名为 singletonObjects(单例池)的 Map 集合中,当调用 getBean 方法时则最终从该 Map 集合中取出 Bean 实例对象返回。

<bean id="" class="" name="" lazy-init="" scope="" init-method="" destroy-method="" factory-bean="" factory-method="" abstract="" depends-on="" parent="">
	<property name="" ref=""/>
	<property name="" ref=""/>
	<property name="" value=""/>
</bean>
public interface BeanDefinition {
	String SCOPE_SINGLETON = "singleton";
	String SCOPE_PROTOTYPE = "prototype";
    
	void setBeanClassName(@Nullable String var1);
	String getBeanClassName();
    
	void setScope(@Nullable String var1);
	String getScope();
    
	void setLazyInit(boolean var1);
	boolean isLazyInit();
    
	void setFactoryBeanName(@Nullable String var1);
	String getFactoryBeanName();
    
	void setFactoryMethodName(@Nullable String var1);
	String getFactoryMethodName();
    
	void setInitMethodName(@Nullable String var1);
	String getInitMethodName();
	//..... 省略部分属性和方法
}

DefaultListableBeanFactory 对象内部维护着一个 Map 用于存储封装好的 BeanDefinitionMap

public class DefaultListableBeanFactory extends ... implements ... {
	//存储<bean>标签对应的BeanDefinition对象
	//key:是Bean的beanName,value:是Bean定义对象BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap;
}

Bean 实例及单例池 singletonObjects beanDefinitionMap 中的 BeanDefinition 会被转化成对应的 Bean 实例对象,存储到单例池 singletonObjects 中去,在 DefaultListableBeanFactory 的上四级父类 DefaultSingletonBeanRegistry 中,维护着 singletonObjects,源码如下:

public class DefaultSingletonBeanRegistry extends ... implements ... {
	//存储Bean实例的单例池
	key:是Bean的beanName,value:是Bean的实例对象
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
}

Bean 实例化的基本流程

  • 加载 xml 配置文件,解析获取配置中的每个 <bean> 的信息,封装成一个个的 BeanDefinition 对象;
  • BeanDefinition 存储在一个名为 beanDefinitionMapMap<String,BeanDefinition> 中;
  • ApplicationContext 底层遍历 beanDefinitionMap,创建 Bean 实例对象;
  • 创建好的 Bean 实例对象,被存储到一个名为 singletonObjectsMap<String,Object> 中;
  • 当执行 applicationContext.getBean(beanName) 时,从 singletonObjects 去匹配 Bean 实例返回。

Bean 生命周期

Spring Bean 的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到 Bean 成为一个完整对象,最终存储到单例池中,这个过程被称为 Spring Bean 的生命周期。Spring Bean 的生命周期大体上分为三个阶段:

  • Bean 的实例化阶段:Spring 框架会取出 BeanDefinition 的信息进行判断当前 Bean 的范围是否是singleton 的,是否不是延迟加载的,是否不是 FactoryBean 等,最终将一个普通的 singleton 的 Bean 通过反射进行实例化;
  • Bean 的初始化阶段:Bean 创建之后还仅仅是个"半成品",还需要对 Bean 实例的属性进行填充、执行一些 Aware 接口方法、执行 BeanPostProcessor 方法、执行 InitializingBean 接口的初始化方法、执行自定义初始化 init 方法等。该阶段是 Spring 最具技术含量和复杂度的阶段:Aop 增强功能,Spring 注解功能、Bean 循环引用问题都是在这个阶段体现的;
  • Bean 的完成阶段:经过初始化阶段,Bean 就成为了一个完整的 Spring Bean,被存储到单例池 singletonObjects 中去了,即完成了 Spring Bean 的整个生命周期。

Spring Bean 的初始化过程涉及如下几个过程:

  • Bean实例的属性填充
  • Aware接口属性注入
  • BeanPostProcessor的before()方法回调
  • InitializingBean接口的初始化方法回调
  • 自定义初始化方法init回调
  • BeanPostProcessor的after()方法回调

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到