基于xml的Spring应用之SpringBean的配置详解

SpringBean的配置详解
Spring开发中主要是对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-imethod=“”

Bean实例销毁前的方法,method指定方法名

<bean autowire=“byType”

设置自动注入模式,常用的有按照类型byType,按照名字byName

<bean factory-bean=“” factory-mentod=“”/

指定哪个方法完成Bean的创建


2) Bean的别名配置

可以为当前Bean指定多个别名,根据别名也可以获得Bean对象

<bean id="userDao" name="aaa,bbb" class="com.luxifa.dao.impl.UserDaoImpl"/">

此时多个名称都可以获得UserDaoImpl实例对象

applicationContext.getBean("userDao");
applicationContext.getBean("aaa");
applicationContext.getBean("bbb");

3) Bean的范围配置
默认情况下,单纯的Spring环境Bean的作用范围有两个,Singleton和Prototype

  • singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
  • prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。

4) Bean的延迟加载
当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可,本质上该Bean还是单例的

<bean id="userDao" class="com.luxifa.dao.impl.UserDaoImpl" lazy-init="true"/>

5) Bean的初始化和销毁方法配置
Bean在被实例化后,可以执行指定的初始化方法完成一些初始化的操作,Bean在销毁之前也可以执行指定的销毁方法完成一些操作,初始化方法名称和销毁方法名称通过

<bean id="userDao" class="com.luxifa.dao.impl.UserDaoImpl" init-method=“init” destroy-method=“destory”/>
public class UserDaoImpl implements UserDao{
	public UserDaoimpl() {System.out.println("UserDaoimpl创建了...");}
	public void init() {System.out.println("初始化方法,,,");}
	public void destroy() {System.out.println("销毁方法,,,");}
}

控制台打印:

UserDaoimpl创建了...
初始化方法,,,

扩展:除此之外,我们还可以通过实现InitializingBean接口,完成一些Bean的初始化操作,如下:

public class UserDaoImpl implements UserDao,InitializingBean {
	public UserDaoimpl() {System.out.println("UserDaoimpl创建了...");}
	public void init() {System.out.println("初始化方法,,,");}
	public void destroy() {System.out.println("销毁方法,,,");}
	//执行时机早于init-method配置的方法
	public void afterpropertiesSet() throws Exception {	System.out.println("InitializingBean...")}
}

控制台打印:

UserDaoimpl创建了...
InitializingBean...
初始化方法,,,

6) Bean的实例化配置
Spring的实例化方式主要如下两种:

  • 构造方式实例化:底层通过构造方法对Bean进行实例化
  • 工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化

构造方法实例化Bean又分为无参构造方法实例化和有参构造方法实例化,Spring中配置的几乎都是无参构造方式。下面是有参构造方法实例化Bean

//有参构造方法
public UserDaoImpl(String name) {
}

有参构造在实例化Bean时,需要参数的注入,通过标签,嵌入在标签内部提供构造参数,如下:

<beam id="userDao" class="com.luxifa,dao.impl.UserDaoImpl">
	<constructor=arg name="name" value="路西法98"/>
</bean>

工厂方式实例化Bean,又分为如下三种:

  • 静态工厂方法实例化Bean
  • 实例工厂方法实例化Bean
  • 实现FactoryBean规范延迟实例化Bean

静态工厂方法实例化Bean:

public class MyBeanFactory1 {
	public static UserDao userDao() {
		return new UserDaoImpl();
	}
}
<beam id="userDao1" class="com.luxifa.factory.MyBeanfactory1" factory-method="userDao">
</bean>

实例工厂方法实例化Bean:

public class MyBeanFactory2 {
	public UserDao userDao() {
		//Bean创建之前可以进行一些其他业务逻辑操作
		return new UserDaoImpl();
	}
}
<!--配置工厂对象-->
<beam id="myBeanFactory2" class="com.luxifa.factory.MyBeanfactory2" factory-method="userDao"></bean>

<beam id="userDao2" factory-bean="myBeanFactory2" factory-method="userDao"></bean>

7) Bean的依赖注入配置

Bean的依赖注入有两种方式:

注入方式

配置方式

通过Bean的set方法注入

<property name=‘userDao" ref=‘userDao’/> <property name=‘userDao’’ value=‘luxifa’/>

通过构造Bean的方法进行注入

<constructor-arg name='name" ref='userDao"/> <constructor-arg name='name" ref=“luxifa”/>

其中,ref是reference的缩写形式,涉及,参考的意思,用于引用其他Bean的id。value用于注入普通属性值。

依赖注入的数据类型有如下三种:

  • 普通数据类型,例如:String、int、boolean等,通过value属性指定。
  • 引用数据类型,例如:UserDaoImpl、DataSource等,通过ref属性指定。
  • 集合数据类型,例如:List、Map、Properties等。

List:

public class UserServiceImpl implements UserService {
	
	//注入List
	private List<String> stringList;
	public void setStringList(List<String> stringList) {
		this.stringList = stringList;
	}
}
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="stringList">
		<list>
			<value>aaa</value>
			<value>bbb</value>
			<value>ccc</value>
		</list>
	</property>
</bean>
public class UserServiceImpl implements UserService {
	
	//注入List
	private List<UserDao> userDaoList;
	public void setStringList(List<UserDao> userDaoList) {
		this.userDaoList= userDaoList;
	}
}

方式一

<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="userDaoList">
		<list>
			<bean class="com.luxifa.dao.impl.UserDaoImpl"></bean>
			<bean class="com.luxifa.dao.impl.UserDaoImpl"></bean>
			<bean class="com.luxifa.dao.impl.UserDaoImpl"></bean>
		</list>
	</property>
</bean>

方式二

<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="userDaoList">
		<list>
			<ref bean="userDao1"></ref>
			<ref bean="userDao2"></ref>
			<ref bean="userDao3"></ref>
		</list>
	</property>
</bean>

<bean id=“userDao1” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao2” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao3” class="com.luxifa.dao.impl.UserDaoImpl"></bean>

Set:

public class UserServiceImpl implements UserService {
	
	//注入Set
	private Set<String> strSet;
	public void setStrSet(Set<String> strSet) {
		this.strSet= strSet;
	}

	private Set<UserDao> userDaoSet;
	public void setUserDaoSet(Set<UserDao> userDaoSet) {
		this.userDaoSet = userDaoSet;
	}
}
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="strSet">
		<set>
			<value>xxxx</value>
			<value>yyyy</value>
			<value>zzzz</value>
		</set>
	</property>
	<property name="userDaoList">
		<list>
			<ref bean="userDao1"></ref>
			<ref bean="userDao2"></ref>
			<ref bean="userDao3"></ref>
		</list>
	</property>
</bean>
<bean id=“userDao1” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao2” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao3” class="com.luxifa.dao.impl.UserDaoImpl"></bean>

Map:

public class UserServiceImpl implements UserService {
	
	//注入Set
	private Map<String,UserDao> map;
	public void setMap(Map<String,userDao> map) {
		this.map = map;
	}
	
}
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="map">
		<map>
			<entry key="d1" value-ref="userDao1">xxxx</value>
			<entry key="d2" value-ref="userDao2">xxxx</value>
		</map>
	</property>
	<property name="userDaoList">
		<list>
			<ref bean="userDao1"></ref>
			<ref bean="userDao2"></ref>
			<ref bean="userDao3"></ref>
		</list>
	</property>
</bean>
<bean id=“userDao1” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao2” class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id=“userDao3” class="com.luxifa.dao.impl.UserDaoImpl"></bean>

Properties:

public class UserServiceImpl implements UserService {
	
	private Properties properties;
	public void setProperties(Properties  properties) {
		this.properties= properties;
	}	
}
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl">
	<property name="properties">
		<props>
			<prop key="p1">ppp1</value>
			<prop key="p2">ppp2</value>
		</props>
	</property>
</bean>
  1. Bean的依赖注入配置
    扩展:自动装配方式
    如果被注入的属性类型是Bean引用的话,那么可以在标签中使用autowire属性去配置自动注入方式,属性值有两个:
  • byName:通过属性名自动装配,即去匹配setXxx与id=“xxx”(name=“xxx”)是否一致;
  • byType:通过Bean的类型从容器中匹配,匹配出多个相同Bean类型时,报错。
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl" autowire=“byType”>

byName:

public class UserServiceImpl implements UserService {
	
	private UserDao userDao;

	//BeanFactory去调用该方法 从容器中获得userDao2设置到此处
	public void setUserDao2(UserDao userDao) {
		this.userDao = userDao;
	}	
}
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl" autowire=“byName”></bean>

<bean id="userDao2" class="com.luxifa.dao.impl.UserDaoImpl"></bean>

  1. Spring的其他配置标签
    Spring的xml标签大体上氛围两类,一种是默认标签,一种是自定义标签
  • 默认标签:就是不用额外导入其他命名空间约束的标签,例如标签
  • 自定义标签:就是需要额外引入其他命名空间约束,并通过前缀引用的标签,例如context:property-placeholder/标签

Spring的默认标签用到的是Spring的默认命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
</beans>

该命名空间约束下的默认标签如下:

标签

作用

beans

一般作为xml配置根标签,其他标签都是该标签的子标签

bean

Bean的配置标签

import

外部资源导入标签

alias

指定Bean的别名标签,使用较少

beans 标签:

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

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

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

</beans>

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

  • 使用命令行动态参数,虚拟机参数位置加载 -Dspring.profiles.active=test
  • 使用代码的方式设置环境变量 System.setProperty(“spring,profiles.active”,“test”)
<bean id="userDao" class="com.luxifa.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.luxifa.dao.impl.UserServiceImpl">
<!-- 配置测试环境下,需要加载的Bean实例-->
<beans  profile="test">
	<bean id="userDao1" class="com.luxifa.dao.impl.UserDaoImpl"></bean>
</beans>
<!-- 配置开发环境下,需要加载的Bean实例-->
<beans  profile="dev">
	<bean id="userService1" class="com.luxifa.dao.impl.UserServiceImpl"></bean>
</beans>
public class ApplicationContextTest {
	public static void main(String[] args) {
		
		//指定环境
		System.setProperty("spring.profiles.active","test");

		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");

		UserDao userDao = (UserDao) applicationContext.getBean("userDao1");
		Systen.out.println(userDao);
	}
}

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

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

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

alias标签:

alias标签是为某个Bean添加别名,与在bean标签上使用name属性添加别名的方式一样,我们为UserServiceImpl指定四个别民:aaa、bbb、xxx、yyy

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

Spring的其他配置标签
Spring的自定义标签需要引入外部的命名空间,并为外部的命名空间指定前缀,使用<前缀:标签>形式的标签,称为自定义标签,自定义标签的解析流程也是Spring xmll扩展点方式之一

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