Spring系列--Bean标签详解
Bean的配置Spring如同一个工厂,用于生产和管理Spring容器中的Bean。在实际开发中,最常采用XML格式的配置方式,我们将通过XML文件来注册并管理Bean之间的依赖关系。
Bean的配置
Spring如同一个工厂,用于生产和管理Spring容器中的Bean。在实际开发中,最常采用XML格式的配置方式,我们将通过XML文件来注册并管理Bean之间的依赖关系。
在Spring中,XML配置文件的根元素是< beans >,< beans >中可以包含多个< bean >子元素,每一个< bean >子元素定义了一个Bean,并描述了该Bean如何被装配到Spring 容器中。< bean >子元素中包含多个属性和子元素,常用的属性和子元素如下表所示:
在Spring的配置文件中,通常一个普通的Bean只需要定义id(或name)和class两个属性即可。定义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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--将指定类配置给Spring 让Spring创建其对象的实例-->
<!--使用id属性定义bean1,其对应的实现类为com.ssm.Bean1-->
<bean id="bean1" class="com.ssm.Bean1"/>
<!--使用name属性定义bean2,其对应的实现类为com.ssm.Bean2-->
<bean name="bean2" class="com.ssm.Bean2"> </bean>
</beans>
需要注意的是: 如果在Bean中未指定id和name,那么Spring会将class值当作id使用。
Bean的作用域
作用域的种类
Spring中为Bean的实例定义了7种作用域,如下图所示:
其中,singleton和prototype是常用的两种。
singleton作用域
singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean的id属性相匹配,就会返回同一个Bean的实例。singleton作用域对于无会话状态的Bean(如Dao组件、Service组件)来说是最理想的选择。
在Spring配置文件中,Bean的作用域是通过< bean >元素的scope属性来指定的,该属性值可以设置为singleton、prototype、request、session、globalSession、application、websocket七个值。 比如,要将作用域定义成singleton,只需要将scope属性值设置为singleton,代码如下:
<bean id="scope" class="com.ssm.scope.Scope" scope="singleton">
测试singleton作用域
项目创建在上一节中,已经详细介绍过,这里就不多说了。
Scope.java
在com.ssm.scope中创建Scope类,该类不需要写任何方法
package com.ssm.scope;
public class Scope {
}
applicatonContext.xml
在com.ssm.scope包中创建Spring的配置文件applicationContext.xml,并在配置文件中创建一个id为scope的Bean,通过class属性指定其对应的实现类为Scope
<?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.xsd">
<!--将指定类配置给Spring 让Spring创建其对象的实例-->
<bean id="scope" class="com.ssm.scope.Scope" scope="singleton"></bean>
</beans>
ScopeTest.java
在com.ssm.scope包中创建测试类ScopeTest来测试singleton作用域,代码如下:
package com.ssm.scope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ScopeTest {
public static void main(String[] args) {
//1.初始化Spring容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.输出获得的实例
System.out.println(applicationContext.getBean("scope"));
System.out.println(applicationContext.getBean("scope"));
}
运行结果如下:
从中可以看出,两次输出的结果相同,这说明Spring容器只创建了一个Scope类的实例
注意: Spring容器默认的作用域就是singleton。
prototype作用域
对需要保持会话状态的Bean应用使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。
要将Bean定义为prototype作用域,只需在配置文件中将< bean >元素的scope属性值设置为prototype即可,代码如下:
<bean id="scope" class="com.ssm.scope.Scope" scope="prototype">
修改完配置文件后,我们再次运行测试类ScopeTest,输出结果如下:
从中可以看到,两次输出的Bean实例并不相同,这说明在prototype作用域下创建了两个不同的Scope实例。
Bean的装配方式
Bean的装配可以理解为依赖关系注入,Spring容器支持多种形式的Bean装配方式,如基于XML的装配、基于Annotation(注解)的装配和自动装配等。
基于XML的装配
Spring提供了两种基于XML的装配方式; 设值注入(Setter)和构造注入.
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter()方法来注入属性值。因此,设置注入要求Bean必须满足以下两点要求:
- Bean类必须提供一个默认的无参构造方法。
- Bean类必须为需要注入的属性提供对应的setter()方法。
使用设置注入时,在Spring配置文件中需要使用< bean >元素的子元素< property >来为每个属性注入值;而使用构造注入时,在配置文件中需要使用< bean >元素的子元素< constructor-arg >来定义构造方法的参数,可以使用其values属性(或子元素) 来设置该参数的值。
代码实现
User.java
在src/java目录下创建一个com.ssm.assemble包,在该包中创建User类,并在类中定义userName、password和list集合3个属性。代码如下:
package com.ssm.assemble;
import java.util.List;
public class User {
private String userName;
private String password;
private List<String> list;
/**
* 1.使用构造注入:
* 1.1提供所有参数的构造方法
*/
public User(String userName, String password, List<String> list) {
this.userName = userName;
this.password = password;
this.list = list;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
", list=" + list +
'}';
}
/**
* 2.使用设值注入
* 2.1提供默认的空参构造方法
* 2.2为所有属性提供setter()方法
*/
public User() {
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
}
applicationContext.xml
在Spring的配置文件中,增加通过构造注入和设置注入的方法装配User实例的两个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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过构造注入装配Bean-->
<bean id="user1" class="com.ssm.assemble.User">
<constructor-arg index="0" value="小鑫"/>
<constructor-arg index="1" value="726599123"/>
<constructor-arg index="2">
<list>
<value>"小鑫1"</value>
<value>"小鑫2"</value>
</list>
</constructor-arg>
</bean>
<!--通过设值注入装配Bean-->
<bean id="user2" class="com.ssm.assemble.User">
<property name="userName" value="小鑫123"/>
<property name="password" value="721020"/>
<property name="list">
<list>
<value>"小鑫3"</value>
<value>"小鑫4"</value>
</list>
</property>
</bean>
</beans>
< constructor-arg >元素用于定义构造方法的参数,其属性idnex表示其索引(从0开始),value属性用于设置注入的值,其子元素< list >为User类中对应的list集合属性注入值。然后又通过设置注入的方法装配User类的实例,其中< property >元素用于调用Bean实例中的setter()方法完成属性赋值,从而完成依赖注入。
XmlAssembleTest.java
在com.ssm.assemble包中创建测试类XmlAssembleTest,在类中分别获取并输出配置文件中的user1和user2实例,代码如下;
package com.ssm.assemble;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class XmlAssembleTest {
public static void main(String[] args) {
//1.初始化Spring容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.输出获得的实例
System.out.println(applicationContext.getBean("user1"));
System.out.println(applicationContext.getBean("user2"));
}
}
运行程序,结果如下:
基于Annotation的装配
在Spring中,虽然可以使用XML配置文件可以实现Bean的装配工作,但是一旦应用中有很多Bean,就会导致XML配置文件过于臃肿。因此,Spring提供了对Annotation(注解)技术的全面支持。
Spring中定义了一系列的注解,如下表所示:
注意: 虽然@Repository、@Setvice和@Controller的功能与@Component注解的功能相同,但能使标注类本身用途更加清晰,建议使用@Repository、@Setvice和@Controller注解。
代码实现
UserDao.java
在src的目录下创建一个com.ssm.annotation包,在该包中创建接口UserDao,并在接口中定义一个save()方法
package com.ssm.annotation;
public interface UserDao {
public void save();
}
UserDaoImpl.java
在com.ssm.annotation包中创建UserDao接口的实现类UserDaoImpl
package com.ssm.annotation;
import org.springframework.stereotype.Repository;
//使用@Repository注解将UserDaoImpl类标识为Spring中的Bean
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userDao.save()");
}
}
在该类中,首先使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中< bean id=“userDao” class=“com.ssm.annotation.UserDaoImpl” >的编写
UserService.java
在com.ssm.annotation包创建接口UserService,在接口中同样定义一个save()方法, 代码如下:
package com.ssm.annotation;
public interface UserService {
public void save();
}
UserServiceImpl.java
在com.ssm.annotation包中创建UserService接口的实现类UserServiceImpl。代码如下:
package com.ssm.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
//使用@Service注解将UserServiceImpl类标识为Spring中的Bean
@Service("userService")
public class UserServiceImpl implements UserService {
//使用@Resource 注解注入
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("执行 userService.save()");
}
}
在该类中,首先使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中< bean id=“userDao” class=“com.ssm.annotation.UserDaoImpl” >的编写;然后使用@Autowired+@Qualifier(“userDao”)标注在属性userDao上,这相当于配置文件中<property name="userDao"ref="userDao”/>的写法,相当于实现了setter()注入。
UserController.java
在com.ssm.annotation包中创建控制器类UserController,代码如下:
package com.ssm.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
//使用@Controller注解将UserController类标识为Spring中的Bean
@Controller("UserController")
public class UserController {
//使用@Resource注解注入
@Autowired
@Qualifier("userService")
private UserService userService;
public void save(){
userService.save();
// System.out.println(userService);
System.out.println("运行userController.save()");
}
}
在该类中,我们使用@Controller注解标注了UserController类,这相当于在配置文件中编写< bean id=“userController” class=" com.ssm.annotation.UserController" />;其余的和UserServiceImpl类似,就不多说了。
applicationContext.xml
<?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命名控件在配置文件中开启相应的注解处理器-->
<context:annotation-config/>
<!--分别定义3个Bean实例-->
<bean id="userDao" class="com.ssm.annotation.UserDaoImpl"/>
<bean id="userService" class="com.ssm.annotation.UserServiceImpl"/>
<bean id="userController" class="com.ssm.annotation.UserController"/>
</beans>
首先,在< beans >元素中添加了包含context的约束信息;然后通过配置< context: annotation-config/>来开启注解处理器,最后分别定义了3个Bean对应的3个实例。与XML配置方式有所不同的是,这里不再需要配置子元素。
上述Spring配置文件中的注解方式虽然较大程度地简化了XML文件中Bean的配置,但仍需在Spring配置文件中一一配置相应的Bean,为此Spring注解提供了另一种高效的注解配置方法(对包路径下的所有Bean文件进行扫描),代码如下:
<context:component-scan base-package="com.ssm.annotation"/>
这一行代码就相当于将annotation包下,只要添加了Spring注解的类,都添加到了Spring容器中。
需要注意的是:对指定包中的注解进行扫描前,先向项目中导入SpringAOP的JAR包spring-aop-5.0.2.RELEASE.jar,不然会报错。
AnnotationAssembleTest.java
在com.ssm.annotation包中创建测试类AnnotationAssembleTest
package com.ssm.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationAssembleTest {
public static void main(String[] args) {
//1.初始化Spring容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取UserController实例
UserController userController = (UserController) applicationContext.getBean("userController");
//调用UserController中的save()方法
userController.save();
}
}
执行程序后,效果如下图所示:
自动装配
Spring的< bean >元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean,所谓自动装配,就是将一个Bean自动注入其他Bean的Property中
antowire属性有5个值,如下表所示:
代码实现
修改UserServiceImpl.java和UserController.java
//使用@Service注解将UserServiceImpl类标识为Spring中的Bean
@Service("userService")
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
System.out.println("执行 userService.save()");
}
}
//使用@Controller注解将UserController类标识为Spring中的Bean
@Controller("UserController")
public class UserController {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public void save(){
userService.save();
// System.out.println(userService);
System.out.println("运行userController.save()");
}
}
我们取消了通过注解注入的,为其属性设置了setter()方法.
修改applicationContext.xml
<?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命名控件在配置文件中开启相应的注解处理器-->
<context:annotation-config/>
<!--分别定义3个Bean实例-->
<bean id="userDao" class="com.ssm.annotation.UserDaoImpl"/>
<bean id="userService" class="com.ssm.annotation.UserServiceImpl" autowire="byName"/>
<bean id="userController" class="com.ssm.annotation.UserController" autowire="byName"/>
</beans>
在配置文件中,用于配置userService和userController的< bean >元素中除了id和class属性外,还增加了autowire属性,将其属性值设置为byName; 设置了autowire="byName"后,Spring会自动寻找userServiceBean中的属性,并将其属性名称与配置文件中定义的Bean做匹配,由于UserServiceImpl中定义了userDao属性及其setter()方法,这与配置文件中id为userDao的Bean相匹配,因此Spring会自动地将id为userDao的Bean装配到id为userService的Bean中。
运行程序,效果如下:
更多推荐
所有评论(0)