学习笔记 : Spring Bean
Bean 的配置
简介 : Spring可以被看成一个大型工厂,其作用是生产
和管理
Spring容器中的Bean
,前提是需要在Sring配置文件中进行配置. Spring容器支持XML
和Properties
两种格式的配置文件.其前者最为常用哟! 在配置文件中,通常为一个Bean配置id
或name
和class
两个属性即可,注意的是如果Bean中未指定id和name,则Spring会将class值当做id使用.
Bean 的实例化
简介 : 在Spring中,想要使用容器中的Bean时需要先将其实例化,其实例化的方式有三种,如下所示.
- 构造器实例化(
最常用
) : Spring容器通过Bean对应类中默认的无参构造方法来实例化Bean. - 静态工厂方式实例化 : 将Bean配置中的class属性指定静态工厂类,然后使用
factory-method
属性来指定所创建的静态工厂方法. - 实例工厂方式实例化 : 将需要实例化的Bean通过
factory-bean
属性指向配置的实例工厂,然后使用factory-method
属性确定使用工厂中的具体方法.
Bean 的实例化案例
通过一个示例程序来演示实例化Bean的三种方式.
Bean类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package pers.huangyuhui.spring.bean.instance;
//构造器实例化
public class Bean1 {
}
package pers.huangyuhui.spring.bean.instance;
//静态工厂方式实例化
public class Bean2 {
}
package pers.huangyuhui.spring.bean.instance;
//实例工厂方式实例化
public class Bean3 {
}MyBean2Factory.java : 静态工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package pers.huangyuhui.spring.bean.factory;
import pers.huangyuhui.spring.bean.instance.Bean2;
/**
* @ClassName: MyBean2Factory
* @Description: 静态工厂方式实例化
* @author: HuangYuhui
* @date: May 24, 2019 2:08:00 PM
*
*/
public class MyBean2Factory {
public static Bean2 createBean() {
return new Bean2();
}
}MyBean3Factory.java : 实例工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package pers.huangyuhui.spring.bean.factory;
import pers.huangyuhui.spring.bean.instance.Bean3;
/**
* @ClassName: MyBean3Factory
* @Description: 实例工厂方式实例化
* @author: HuangYuhui
* @date: May 24, 2019 2:16:03 PM
*
*/
public class MyBean3Factory {
public MyBean3Factory() {
System.out.println("this is constructor ~");
}
public Bean3 createBean() {
return new Bean3();
}
}applicationContext.xml : Spring核心配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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="bean1" class="pers.huangyuhui.spring.bean.instance.Bean1"/>
<!-- 静态工厂方式实例化 -->
<!-- factory-method: 指定工厂方法 -->
<bean id="bean2" class="pers.huangyuhui.spring.bean.factory.MyBean2Factory" factory-method="createBean"/>
<!-- 实例工厂方式实例化 -->
<!-- factory-bean:指定配置的实例工厂 -->
<bean id="myBean3Factory" class="pers.huangyuhui.spring.bean.factory.MyBean3Factory"/>
<bean id="bean3" factory-bean="myBean3Factory" factory-method="createBean"/>
</beans>InstanceTest.java : 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package pers.huangyuhui.spring.bean.instance.test;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.huangyuhui.spring.bean.instance.Bean1;
/**
* @ClassName: InstanceTest
* @Description: 测试
* @author: HuangYuhui
* @date: May 24, 2019 1:57:41 PM
*
*/
public class InstanceTest {
private static ApplicationContext applicationContext;
public static void init() {
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
// 构造器实例化
public void instanceTest1() {
Bean1 bean1 = applicationContext.getBean(Bean1.class);
// result : pers.huangyuhui.spring.bean.instance.Bean1@59402b8f
System.out.println(bean1);
}
// 静态工厂方式实例化
public void instanceTest2() {
// result : pers.huangyuhui.spring.bean.instance.Bean2@70ed52de
System.out.println(applicationContext.getBean("bean2"));
}
// 实例工厂方式实例化
public void instanceTest3() {
// result :
// this is constructor ~
// pers.huangyuhui.spring.bean.instance.Bean3@70ed52de
System.out.println(applicationContext.getBean("bean3"));
}
}
Bean 的作用域
简介 : 在Spring 4.3中为Bean定义了七种作用域,如下所示.
- Singleton(
单例
) : 使用Singleton定义的Bean在Spring容器中将只有一个实例,也就是说,无论有多少个Bean引用它,始终指向同一个对象,其也是Spring默认的作用域. - prototype(
原型
) : 每次通过Spring容器获取prototype定义的Bean时,容器都将创建一个新的Bean实例. - request : ..
- session : ..
- globalSession : ..
- application : ..
- websocket : ..
Bean 的作用域案例
下面通过简单程序来分别演示singleton
和prototype
作用域
Bean类
1
2
3
4
5
6
7
8
9
10
11
12package pers.huangyuhui.spring.bean.scope;
//Bean的作用域: singleton
public class Bean4 {
}
package pers.huangyuhui.spring.bean.scope;
//Bean的作用域: prototype
public class Bean5 {
}Spring核心配置文件
1
2
3
4
5
6
7
8
9
10
11
<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">
<!-- singleton(default) -->
<bean id="bean4" class="pers.huangyuhui.spring.bean.scope.Bean4" scope="singleton"/>
<!-- prototype -->
<bean id="bean5" class="pers.huangyuhui.spring.bean.scope.Bean5" scope="prototype"/>
</beans>测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44package pers.huangyuhui.spring.bean.scope.test;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName: ScopeTest
* @Description: 测试
* @author: HuangYuhui
* @date: May 24, 2019 2:53:10 PM
*
*/
public class ScopeTest {
private static ApplicationContext applicationContext;
public static void init() {
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
// Bean的作用域: singleton
public void singletonTest() {
// result:
// pers.huangyuhui.spring.bean.scope.Bean4@7c137fd5
// pers.huangyuhui.spring.bean.scope.Bean4@7c137fd5
System.out.println(applicationContext.getBean("bean4"));
System.out.println(applicationContext.getBean("bean4"));
}
// Bean的作用域: prototype
public void prototypeTest() {
// result: pers.huangyuhui.spring.bean.scope.Bean5@3e08ff24
System.out.println(applicationContext.getBean("bean5"));
}
}
Bean 的装配方式
简介 : Bean的装配方式可以理解为依赖注入,Bean的装配方式既Bean依赖注入的方式. Spring容器支持多种形式的Bean的装配方式,如基于XML
的装配,基于Annotation
的装配等..
基于XML的装配
Spring提供了两种基于XML的装配方式: 设值注入(Setter Injection
)和构造注入(Constructor Injection
). 在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方式来注入属性值
.因此,设值注入要求一个Bean必须满足一下两点要求.
- Bean类必须提供一个默认的无参构造方法.
- Bean类必须为需要注入的属性提供对应的
setter
方法.
下面通过一个简单示例程序来展示基于XML的Bean的装配方式.
User.java : Java bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package pers.huangyuhui.spring.assemble.bean;
import java.util.List;
/**
* @ClassName: User
* @Description: 用户信息
* @author: HuangYuhui
* @date: May 24, 2019 3:37:58 PM
*
*/
public class User {
private String name;
private List<String> phone;
public User() {
}
public User(String name, List<String> phone) {
super();
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getPhone() {
return phone;
}
public void setPhone(List<String> phone) {
this.phone = phone;
}
public String toString() {
return "User [name=" + name + ", phone=" + phone + "]";
}
}applicationContext.xml : Spring核心配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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">
<!-- 利用构造注入方式装配User实例 -->
<bean id="user1" class="pers.huangyuhui.spring.assemble.bean.User">
<constructor-arg index="0" value="YUbuntu0109-1"/>
<constructor-arg index="1">
<list>
<value>"15111111111"</value>
<value>"15211111111</value>
</list>
</constructor-arg>
</bean>
<!-- 使用设值注入方式装配User实例 -->
<bean id="user2" class="pers.huangyuhui.spring.assemble.bean.User">
<property name="name" value="YUbuntu0109-2"/>
<property name="phone">
<list>
<value>"13111111111"</value>
<value>"18111111111"</value>
</list>
</property>
</bean>
</beans>AssembleTest.java : 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package pers.huangyuhui.spring.assemble.test;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.huangyuhui.spring.assemble.controller.UserController;
/**
* @ClassName: AssembleTest
* @Description: 测试
* @author: HuangYuhui
* @date: May 24, 2019 3:49:42 PM
*
*/
public class AssembleTest {
private static ApplicationContext applicationContext;
public static void init() {
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
// @Ignore
// 测试基于XML的Bean配置
public void xmlBeanAssembleTest() {
// result: User [name=YUbuntu0109-1, phone=["15111111111", "15211111111]]
System.out.println(applicationContext.getBean("user1"));
// result: User [name=YUbuntu0109-2, phone=["13111111111", "18111111111"]]
System.out.println(applicationContext.getBean("user2"));
}
}
基于Annotation的装配
简介 : 通过注解(Annotation
)来实现Bean的装配工作可以解决XML配置文件过于臃肿的问题,且便于后期维护. 其常用注解如下.
@Repository
: 用于将数据访问层(DAO层)的类标识为Spring中的Bean.@Service
: 通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean.@Controller
: 通过作用在控制层(如Spring MVC的Controller),用于将控制层的类标识为Spring中的Bean.@Autowired
: 用于对Bean的属性变量,属性的setter方法及构造方法进行标注,配合对用的注解处理器来完成Bean的自动配置工作.
下面通过一个简单案例来演示如何通过这些注解来装配Bean.
UserDao.java
1
2
3
4
5
6package pers.huangyuhui.spring.assemble.dao;
public interface UserDao {
public void save();
}UserDaoImple.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package pers.huangyuhui.spring.assemble.dao.impl;
import org.springframework.stereotype.Repository;
import pers.huangyuhui.spring.assemble.dao.UserDao;
/**
* @ClassName: UserDaoImpl
* @Description: UserDao的实现类
* @author: HuangYuhui
* @date: May 24, 2019 4:13:53 PM
*
*/
// 将UserDaoImpl类标识为Spring中的Bean
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("UserDao : Save function ~");
}
}
- 其中使用
@Respository
注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中的<bean id="userDao" class="pers.huangyuhui.spring.assemble.dao.impl.UserDaoImpl"/>
UserService.java
1
2
3
4
5
6package pers.huangyuhui.spring.assemble.dao;
public interface UserService {
public void save();
}UserServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package pers.huangyuhui.spring.assemble.dao.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pers.huangyuhui.spring.assemble.dao.UserDao;
import pers.huangyuhui.spring.assemble.dao.UserService;
/**
* @ClassName: UserServiceImpl
* @Description: UserService的实现类
* @author: HuangYuhui
* @date: May 24, 2019 4:20:15 PM
*
*/
// 将UserServiceImpl类标识为Spring中的Bean
public class UserServiceImpl implements UserService {
// 自动配置Bean
private UserDao userDao;
public void save() {
userDao.save();
System.out.println("UserService : Save function ~");
}
}UserController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package pers.huangyuhui.spring.assemble.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import pers.huangyuhui.spring.assemble.dao.UserService;
/**
* @ClassName: UserController
* @Description: TODO
* @author: HuangYuhui
* @date: May 24, 2019 4:33:56 PM
*
*/
/// 将UserController类标识为Spring中的Bean
public class UserController {
// 自动配置Bean
private UserService userService;
public void save() {
userService.save();
System.out.println("UserController : Save function ~");
}
}AssembleTest.java : 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package pers.huangyuhui.spring.assemble.test;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.huangyuhui.spring.assemble.controller.UserController;
/**
* @ClassName: AssembleTest
* @Description: 测试
* @author: HuangYuhui
* @date: May 24, 2019 3:49:42 PM
*
*/
public class AssembleTest {
private static ApplicationContext applicationContext;
public static void init() {
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
public void annotationAssembleTest() {
UserController userController = (UserController) applicationContext.getBean("userController");
userController.save();
}
}Spring核心配置文件
1
2
3
4
5
6
7
8
9
10
11
<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-4.3.xsd">
<!-- 扫描指定包下的所有Bean类,进行注解解析 -->
<context:component-scan base-package="pers.huangyuhui.spring.assemble"/>
</beans>程序运行结果
1
2
3UserDao : Save function ~
UserService : Save function ~
UserController : Save function ~