目录
2.1 Bean的配置
- Spring就好比一个工厂,用于生产和管理Spring容器中的Bean,如果你需要使用这个工厂,你就需要对Spring的配置文件进行配置,实际开发中,采用的XML文件格式的配置方式,通过XML文件来注册并管理Bean之间的依赖关系,下面使用XML的形式对Bean的属性和定义解析
- XML配置文件的根元素是< beans>,< beans>中可以有多个< bean>子元素,每一个< bean>子元素都被定义为一个Bean,并描述了该Bean是怎么被装配到Spring容器中的。< bean>子元素中包含了多个属性和子元素,常见的子元素如下
Spring配置文件中,一个普通的Bean只需要定义id和class属性就可以了,定义Bean的方式如下:
分别使用了id属性和name属性定义了两个Bean,并使用class元素指定了其对应的实现类
如果Bean未指定id和name,Spring将会将class值作为id使用
2.2 Bean的作用域
- 通过Spring容器不仅可以完成Bean的实例化,还可以为Bean指定特定的作用域
2.2.1 作用域的种类
- 作用域的种类如下所示,其中最常见的就是singleton和prototype,
2.2.2 singleton作用域
singleton是Spring容器默认的作用域,表示Spring容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id和该Bean的id相同,就会返回同一个Bean实例,singleton对于无会话状态的Bean(组件)来说是最好的选择
Bean的作用域是通过< bean>元素的scope属性指定的,值为上图中的七种
设置scope属性的代码如下
< bean id="scope" class="com.ssm.scope.Scope"
scope="singleton"/>
2.2.3 prototype作用域
对需要保持会话状态的Bean要使用prototype作用域,Spring会为每一个对Bean的请求都创建一个新的实例,
设置的代码如下
< bean id="scope" class="com.ssm.scope.Scope"
scope="prototype"/>
2.3 Bean的装配方式
Bean的装配理解为依赖关系注入,Bean的装配方式就是依赖关系注入的方式。Spring容器支持多种形式的Bean装配方式,基于XML的,基于Annotation的,和自动装配。
2.3.1 基于XML的装配
Spring提供了两种基于XML的装配方式:设置值注入setter,构造注入。
- Spring实例化Bean的过程中,Spring会首先调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式来调用setter()方法注入属性值,所以设置值注入要求一个Bean必须满足以下
- Bean类必须提供一个默认的无参数构造
- Bean类必须为需要注入的属性值提供对应的setter()方法,所以使用设置值注入,Spring配置文件中,需要使用< bean>元素的子元素< property>来为每个属性注入值
- 使用构造注入时,配置文件中需要使用< bean>元素的子元素< constructor-arg>来定义构造方法的参数,使用value属性来设置该参数的值
实例1
- 创建项目,引入jar包
- 在src目录下,创建包和类
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) {
super();
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() {
super();
}
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;
}
}
- 在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-4.3.xsd">
<!-- 将指定类配置给Spring,让Spring创建其对象的实例 -->
<!-- <bean id="scope" class="com.ssm.scope.Scope"/> -->
<bean id="scope" class="com.ssm.scope.Scope" scope="prototype"/>
<bean id="user1" class="com.ssm.assemble.User">
<constructor-arg index="0" value="zhangsan" />
<constructor-arg index="1" value="111111" />
<constructor-arg index="2">
<list>
<value>"constructorValue1"</value>
<value>"constructorValue2"</value>
</list>
</constructor-arg>
</bean>
<bean id="user2" class="com.ssm.assemble.User">
<property name="userName" value="lisi"></property>
<property name="password" value="222222"></property>
<property name="list">
<list>
<value>"listValue1"</value>
<value>"listValue2"</value>
</list>
</property>
</bean>
</beans>
配置文件中有两种方法装配Bean。
- 创建测试类
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"));
}
}
使用Xml的构造注入和设值注入方式装配了User实例
运行结果:
2.3.2 基于Annotation的装配
如果应用中有很多Bean,使用XML配置文件会导致很臃肿,维护麻烦,为此Spring提供了一种对Annotaion注解技术的全面支持
Spring的常用的注释
如图
- 注意:在图的几个注解中,虽然@Repository、@Service和@Controller的功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service和@Controller分别对实现类进行标注。
实例2
- 创建包和类,创建接口UserDao
package com.ssm.annotation;
public interface UserDao {
public void save();
}
- 创建实现类,,实现接口中的方法
package com.ssm.annotation;
import org.springframework.stereotype.Repository;
@Repository("userDao")//使用这个注解将UserDaoImpl这个类标识为Spring中的Bean
public class UserDaoImpl implements UserDao {
public void save() {
System. out. println("执行userDao.save()");
}
}
注意@Repository(“userDao”),将UserDaoImpl类标示为Spring中的Bean
- 创建UserService接口
package com.ssm.annotation;
public interface UserService {
public void save();
}
- UserServiceImpl,实现类
package com.ssm.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDao")
private UserDao userDao;
public void save() {
this.userDao. save();
System.out.println("执行userService.save()");
}
}
- @Service(“userService”),表示将UserServiceImpl类标示为Spring中的Bean
- @Resource(name=“userDao”),表示注入该类,等同于
< property name=“userDao” ref=“userDao”>
- 创建控制器类
package com.ssm.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
@Controller("UserController")
public class UserController {
@Resource(name="userService")
private UserService userService;
public void save(){
this.userService.save();
System.out.println("运行userController.save()");
}
}
- @Controller(“UserController”)表示在配置文件中编写如下代码:
< bean id=“userController” class=“com.ssm.UserController”/>
- @Resource(name=“userService”)相当于
< property name=“userService” ref=“userService”>
- 创建配置文件beans1.xml,编写基于Annotation装配的代码
<?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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.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>
<!-- <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"/>
-->
这里不再需要配置< property>子元素
Spring中还提供了一种更高效的注解配置方式,对包路径下的所有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" />
替换为
- 创建测试类
package com.ssm.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationAssembleTest {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
// 定义配置文件路径
String xmlPath = "com/ssm/annotation/beans1.xml";
applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 获取 UserController实例
UserController userController = (UserController) applicationContext.getBean("userController");
// 调用 UserController中的save()方法
userController.save();
}
}
运行结果如下
2.3.3 自动装配
有没有什么办法可以减少代码量,又可以实现Bean的装配?
Spring的< bean>元素中包含一个autowire属性,我们可以通过使用设置autowire属性来设置自动装配Bean。
自动装配是什么?就是将一个Bean自动注入其他Bean的Property中。
autowire属性有五个值,如图所示
实例3
- 修改UserServiceImpl.java和UserController.java文件,分别加入类属性的setter方法
package com.ssm.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
@Controller("UserController")
public class UserController {
@Resource(name="userService")
private UserService userService;
/*自动装配
* public void setter(UserService userService)
{
this.userService= userService;
}*/
public void save(){
this.userService.save();
System.out.println("运行userController.save()");
}
}
package com.ssm.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDao")
private UserDao userDao;
/*自动装配
* public void setter(UserDao userDao)
{
this.userDao=userDao;
}
*/
public void save() {
this.userDao. save();
System.out.println("执行userService.save()");
}
}
- 最后添加配置文件bean2.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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.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。在默认情况下,配置文件中需要通过ref来装配Bean,但设置了autowire="byName"后,Spring会自动寻找userServiceBean中的属性,并将其属性名称与配置文件中定义的Bean做匹配。由于UserServiceImpl中定义了userDao属性及其setter()方法,这与配置文件中id为userDao的Bean相匹配,因此Spring会自动地将id为userDao的Bean装配到id为userService的Bean中。
本博客来源于《Spring+Spring MVC+MyBatis从零学起》