Note/JAVA/JAVA EE/Web程序设计笔记04——第二章:Spring中的Bean.md
2023-08-31 11:30:31 +08:00

389 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第二章Spring中的Bean
## 9.基于XML的装配
### 什么是Bean的装配
Bean的装配可以理解为依赖关系注入Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式如基于XML的装配、基于注解Annotation的装配和自动装配其中最常用的是基于注解的装配本节将主要讲解这三种装配方式的使用。
1.在 java 包下创建名为 com.ssm.assemble 的包并在包下创建名为 User 的类输入利用生成构造函数、setter方法和toString方法
代码如下:
```java
private String username;
private Integer password;
private List<String> list;
// 1.使用构造注入
// 1.1提供所有参数的有参构造方法。
public User(String username, Integer password, List<String> list) {
this.username = username;
this.password = password;
this.list = list;
}
// 2.使用设值注入
// 2.2提供默认空参构造方法
// 2.3为所有属性提供setter方法
public User() {
super();
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(Integer password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password=" + password +
", list=" + list +
'}';
}
```
2.在 resources 文件下创建名为 beans5.xml 的文件并通过两种方法装配User实例
代码如下:
```java
<!-- 1——1.使用构造方法注入方式装配User实例-->
<bean id="user1" class="com.ssm.assemble.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123456"/>
<constructor-arg index="2">
<list>
<value>"constructorvalue1</value>
<value>"constructorvalue2</value>
</list>
</constructor-arg>
</bean>
<!-- 1——2.使用设值注入方式装配User实例-->
<bean id="user2" class="com.ssm.assemble.User">
<property name="username" value="张三"></property>
<property name="password" value="654321"></property>
<!-- 注入list集合-->
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
</property>
</bean>
```
3.在 com.ssm.assemble 包下创建 XmlBeanAssembleTest 测试类,并运行程序
代码如下:
```java
// 定义配置文件路径
String xmlPath = "beans5.xml";
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 构造方法输出结果
System.out.println(applicationContext.getBean("user1"));
// 构造方法输出结果
System.out.println(applicationContext.getBean("user2"));
```
运行结果如图:
![image-20220310180658138](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220310180658138.png)
### 总结基于XML的装配使用方式
:one:创建 Java 类,提供有参无参构造方法以及属性 setter 方法
:two:创建 Spring 的 xml 配置文件使用两种方式配置Bean
:three:创建测试类,测试程序
## 10.基于Annotation的装配
通过在类上方和成员变量上方添加注解
SSM项目分三层
Dao层接口和实现类——和数据库打交道
```java
//UserDaoImpl 类注解
@Repository("userDao")
```
服务层接口和实现类——调用Dao层
```java
//UserServiceImpl 类注解
@Service("userService")
//UserServiceImpl 成员变量注解
@Resource(name = "userDao")
```
控制层:类——调用服务层
```java
//UserController 类注解
@Resource(name = "userDao")
//UserController 成员变量注解
@Controller("userController")
```
### 1.首先实现三层结构:
创建 com.ssm.annotation 包并在其包下进行以下操作
##### Dao层
创建 UserDao 接口,代码如下:
```java
package com.ssm.annotation;
public interface UserDao {
public void save();
}
```
创建 UserDaoImpl 实现类,代码如下:
```java
package com.ssm.annotation;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userDao...save...");
}
}
```
##### 服务层
创建 UserService 接口,代码如下:
```java
package com.ssm.annotation;
public interface UserService {
public void save();
}
```
创建 UserServiceImpl 实现类,代码如下:
```java
package com.ssm.annotation;
public class UserServiceImpl implements UserService{
private UserDao userDao;
@Override
public void save(){
userDao.save();
System.out.println("Userservice...save...");
}
}
```
可以称为服务层调Dao层
##### 控制层
创建一个 UserController 控制器,代码如下:
```java
package com.ssm.annotation;
public class UserController {
private UserService userService;
public void save() {
userService.save();
System.out.println("userController...save...");
}
}
```
### 2.装配
对Dao层的实现类上方添加注解
```java
//相当于在xml文件中写<bean id="userDao" class="com.ssm.annotaion.UserDaoImpl"/>
@Repository("userDao")
//Repository 仓库 Dao层需要数据库打交道
```
对服务层的实现类以及成员变量上方添加注解
```java
//相当于在xml文件中写<bean id="UserService" class="com.ssm.annotaion.UserServiceImpl"/>
@Service("userService")
@Resource(name = "userDao")
```
对服务层的实现类和成员变量上方添加注解
```java
@Controller("userController")
@Resource(name = "userService")
```
创建 beans6.xml 文件利用xml文件扫描这些包来实现装配
```java
<?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:component-scan base-package="com.ssm.annotation"/>
</beans>
```
创建 Test 测试类
```java
package com.ssm.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans6.xml");
UserController userController = (UserController) applicationContext.getBean("userController");
userController.save();
}
}
```
装配成功运行结果如截图如下:
![image-20220311125821133](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220311125821133.png)
### 3.自动装配
将一个 Bean 自动的注入到其他 Bean 的 property 中Spring 的<Bean>元素中包含一个 autwire 属性,我们可以通过设置 autowire 的属性值来自动装配 Bean 。
| 属性值 | 说明 |
| :---------------: | :----------------------------------------------------------: |
| default默认值 | 由<bean>的上级标签<beans>的 default-autowire 属性值确定。例如<beans>default-autowire="byName">,则该<bean>元素中的 autowire 属性对应的属性值就为byName。 |
| byNamee | 根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean并将其属性自动装配。 |
| byTypee | 根据属性的数据类型Type自动装配如果一个Bean的数据类型兼容另一个Bean中属性的数据类型则自动装配。 |
| constructor | 根据构造函数参数的数据类型进行byType模式的自动装配。 |
| no | 默认情况下不使用自动装配Bean 依赖必须通过 ref元素定义。 |
自动装配一定要有 setter 方法
分别创建类A、B
```java
package com.ssm.autoware;
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
void a(){
b.b();
System.out.println("a");
}
}
```
```java
package com.ssm.autoware;
public class B {
void b(){
System.out.println("b");
}
}
```
填写 xml 装配文件
```java
<?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="b" class="com.ssm.autoware.B"/>
<bean id="a" class="com.ssm.autoware.A" autowire="byName"/>
</beans>
```
最后通过 Test 文件测试
```java
package com.ssm.autoware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("beans7.xml");
A a = (A) applicationContext.getBean("a");
a.a();
}
}
```
### 2.5作用域
| 作用域名称 | 说明 |
| :---------------: | :----------------------------------------------------------: |
| singleton单例 | 使用singleton定义的Bean在Spring容器中将只有一个实例也就是说无论有多少个Bean引用它始终将指同一个对象。这也是Spring容器默认的作用域。 |
| prototype原型 | 每次通过 Spring 容器获取的 prototype 定义的 Bean 时,容器都将建一个新的 Bean实例。 |
| requesto | 在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。对不同的 HTTP 请求则会产生一个新的 Bean而且该 Bean 仅在当前HTTP Request内有效。 |
| sessione | 在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。对不同的 HTTP 请求则会产生一个新的 Bean且该 Bean 仅在当前 HTTP Session 内有效。 |
| globalSessione | 在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。仅在使用portlet上下文时有效。 |
| applicatione | 为每个 ServletContext 对象创建一个实例。仅在 Web 相关的ApplicationContext中生效。 |
| websocket | 为每个 websocket对象创建一个实例。仅在 Web 相关的ApplicationContext中生效。 |
### 2.8生命周期
了解Spring中Bean生命周期有何意义
了解Spring中Bean的生命周期的意义就在于可以利用Bean在其存活期间的特定时刻完成一些相关操作。这种时刻可能有很多但一般情况下常会在Bean的postinitiation(初始化后)和predestruction销毁前执行一些相关操作。
| | |
| :-------------: | :----------------------------------------------------------: |
| singleton作用域 | Spring容器可以管理singleton作用域的Bean的生命周期在此作用域下Spring能够精确的知道该Bean何时被创建何时初始化完成以及何时被销毁。 |
| prototype作用域 | prototype作用域的Bean,Spring只负责创建当容器创建了Bean实例后Bean的实例就交给客户端代码来管理Spring容器将不再跟踪其生命周期。 |