Spring Framework 基础 —— 第三章 Spring 配置文件
1. Bean 标签基本配置
用于配置对象交由 Spring 来创建。
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
基本属性:
id
:Bean 实例在 Spring 容器中的唯一标识class
:Bean 的全限定名称
2. Bean 标签的配置范围
Scope
:指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | (默认)单例的 |
prototype | 多列的 |
Request | Web 项目中,Spring 创建一个 Bean 对象,将对象存入到 request 域中 |
session | Web 项目中,Spring 创建一个 Bean 对象,将对象存入到 session 域中 |
global session | Web 项目中,应用在 Portlet 环境,如果没有 Portlet 环境,那么 golbalSession 相当于 session |
测试代码:
com.yourname.test.SpringTest
import com.gregperlinli.dao.UserDao;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
/**
* Test scope attribute
*/
@Test
public void test1() {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
}
}
测试结果:
scope="singletion"
com.gregperlinli.dao.impl.UserDaoImpl@342c38f8
com.gregperlinli.dao.impl.UserDaoImpl@342c38f8
scope="prototype"
com.gregperlinli.dao.impl.UserDaoImpl@4f2b503c
com.gregperlinli.dao.impl.UserDaoImpl@bae7dc0
注意⚠️:
- 当
scope
取值为singleton
时:- Bean 的实例化个数:1个
- Bean 的实例化时机:当 Spring 核心配置文件被加载时,实例化配置 Bean 实例
- Bean 的生命周期:
- 对象创建:当应用加载,创建容器时,对象就已经创建了
- 对象运行:只要容器在,对象就一直活着
- 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
- 当
scope
取值为prototype
时:- Bean 的实例化个数:多个
- Bean 的实例化时机:当调用
getBean()
方法时实例化 Bean - Bean 的生命周期:
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在容器中,就一直活着
- 对象销毁:当对象长时间不用时,被 Java 垃圾回收器回收了
3. Bean 生命周期配置
init-method
:指定类中的初始化方法名称destroy-method
:制定类中的销毁方法名称
测试代码:
com.yourname.dao.impl.UserDaoImpl
import com.gregperlinli.dao.UserDao;
public class UserDaoImpl implements UserDao {
public UserDaoImpl() {
System.out.println("UserDaoImpl created......");
}
public void init() {
System.out.println("Initialize method...");
}
public void destroy() {
System.out.println("Destroy method...");
}
@Override
public void save() {
System.out.println("Save running......");
}
}
applicationContext
<?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 id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl" scope="prototype" init-method="init" destroy-method="destroy"></bean>
</beans>
com.yourname.test.SpringTest
import com.gregperlinli.dao.UserDao;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
/**
* Test scope attribute
*/
@Test
public void test1() {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
System.out.println(userDao);
app.close();
}
}
测试结果:
UserDaoImpl created......
Initialize method...
com.gregperlinli.dao.impl.UserDaoImpl@32502377
Destroy method...
4. Bean 实例化的三种方式
无参构造方法实例化(重点)
工厂静态方法实例化
工厂实例方法实例化
示例代码:
工厂静态方法实例化
com.yourname.factory.StaticFactory
import com.gregperlinli.dao.UserDao; import com.gregperlinli.dao.impl.UserDaoImpl; public class StaticFactory { public static UserDao getUserDao() { return new UserDaoImpl(); } }
applicationContext
<?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 id="userDao" class="com.gregperlinli.factory.StaticFactory" factory-method="getUserDao"></bean> </beans>
工厂实例方法实例化
com.yourname.factory.DynamicFactory
import com.gregperlinli.dao.UserDao; import com.gregperlinli.dao.impl.UserDaoImpl; public class DynamicFactory { public UserDao getUserDao() { return new UserDaoImpl(); } }
applicationContext
<?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 id="factory" class="com.gregperlinli.factory.DynamicFactory"></bean> <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean> </beans>
5. Bean 的依赖注入分析
示例代码:
com.yourname.service.UserService
public interface UserService {
public void save();
}
com.yourname.service.impl.UserServiceImpl
import com.gregperlinli.dao.UserDao;
import com.gregperlinli.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
}
com.yourname.demo.UserController
import com.gregperlinli.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
}
applicationContext
<?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 id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl"></bean>
</beans>
目前 UserService
实例和 UserDao
实例都写在 Spring 容器中,当前做法是在容器外获取 UserService
实例和 UserDao
实例,然后再程序中进行结合。
因为 UserService
和 UserDao
都在容器中,而最终的程序直接使用的是 UserService
,所以可在 Spring 容器中,将 UserDao
设置到 UserService
内部。
6. 依赖注入概念
依赖注入(Dependency Injection
简称 DI):它是 Spring 核心框架 IoC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IoC 解耦只是降低它们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把持久层对像传入业务层,而不用我们自己去获取。
7. Bean 的依赖注入方式
怎么将 UserDao
注入到 UserService
内部呢?主要有两种方式:
构造方法
set
方法
示例代码:
set
方法注入
com.yourname.service.impl.UserServiceImpl
import com.gregperlinli.dao.UserDao; import com.gregperlinli.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.save(); } }
com.yourname.demo.UserController
import com.gregperlinli.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserController { public static void main(String[] args) { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) app.getBean("userService"); userService.save(); } }
applicationContext
<?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 id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> </beans>
set
方法注入的简便化 —— P 命名空间注入 P 命名空间注入本质也是
set
方法注入,但比起上述的set
方法注入更为简便,主要体现在配置文件中,如下所示: 首先,在
beans
标签内引入 P 命名空间:<beans ... xmlns:p="http://www.springframework.org/schema/p" ... ></beans>
其次,需要修改注入方式:
<bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
简化后效果如下:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl" p:userDao-ref="userDao"/> </beans>
构造方法注入
com.yourname.service.impl.UserServiceImpl
import com.gregperlinli.dao.UserDao; import com.gregperlinli.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; public UserServiceImpl() { } public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.save(); } }
application.Context
<?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 id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean> </beans>
8. Bean 的依赖注入的数据类型
上面的操作,都是注入要引用的 Bean,除了对象的引用可以注入,普通的数据类型,集合等都可以在容器中进行注入。
注入数据的三种数据类型:
普通数据类型
引用数据类型
集合数据类型
示例代码:
com.yourname.dao.impl.UserDaoImpl
import com.gregperlinli.dao.UserDao;
import com.gregperlinli.domain.User;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class UserDaoImpl implements UserDao {
private List<String> strList;
private Map<String, User> userMap;
private Properties properties;
private String username;
private int age;
public UserDaoImpl() {
System.out.println("UserDaoImpl created......");
}
public void setUsername(String username) {
this.username = username;
}
public void setAge(int age) {
this.age = age;
}
public void setStrList(List<String> strList) {
this.strList = strList;
}
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void init() {
System.out.println("Initialize method...");
}
public void destroy() {
System.out.println("Destroy method...");
}
@Override
public void save() {
System.out.println("Username: " + username);
System.out.println("Age: " + age);
System.out.println(strList);
System.out.println(userMap);
System.out.println(properties);
System.out.println("Save running......");
}
}
com.yourname.domain.User
public class User {
private String name;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.gregperlinli.dao.impl.UserDaoImpl">
<property name="username" value="Xiao Ming"/>
<property name="age" value="18"/>
<property name="strList">
<list>
<value>String1</value>
<value>String2</value>
<value>String3</value>
</list>
</property>
<property name="userMap">
<map>
<entry key="User1" value-ref="user1"></entry>
<entry key="User2" value-ref="user2"></entry>
<entry key="User3" value-ref="user3"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">prop1</prop>
<prop key="p2">prop2</prop>
<prop key="p3">prop3</prop>
</props>
</property>
</bean>
<bean id="user1" class="com.gregperlinli.domain.User">
<property name="name" value="Tom"/>
<property name="address" value="Beijing"/>
</bean>
<bean id="user2" class="com.gregperlinli.domain.User">
<property name="name" value="Lucy"/>
<property name="address" value="Shanghai"/>
</bean>
<bean id="user3" class="com.gregperlinli.domain.User">
<property name="name" value="Jerry"/>
<property name="address" value="Guangzhou"/>
</bean>
<bean id="userService" class="com.gregperlinli.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
</beans>
9. 引入其他配置文件(分模块开发)
在实际开发中,Spring 的配置内容非常多,这就导致 Spring 的配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在 Spring 住配置文件通过 import
标签进行加载。
<import resource="applicationContext-xxx.xml"/>
10. Spring 重点配置(重点)
<bean>
标签
id
属性:在容器中 Bean 实例的唯一标识,不允许重复
class
属性:要实例化的 Bean 的全限定名
scope
属性:Bean 的作用范围,常用是 singleton
(默认)和 prototype
<property>
标签:属性注入
name
属性:属性名称
value
属性:注入的普通属性值
ref
属性:注入的对象引用值
<list>
标签
<map>
标签
<properties>
标签
<constructor-arg>
标签:有参构造注入
<import>
标签:导入其他的 Spring 的分配置文件