JavaEE实验
2021/2022(1)
实验9 spring-prj2
学生姓名 张坤
学生学号 201906061726
学生班级 软件工程1903
任课教师 韩珊珊
提交日期 2021年12月2日
计算机科学与技术学院
一、基础实验——Spring 容器中的依赖注入
实验内容及步骤
新建项目
导入maven包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.8</version>
</dependency>
搭建spring框架
在spring-prj2 中新建cn.edu.zjut.bean 包,并在其中创建IItem 接口(代码略)及其实现类Item(代码片段如下);
public interface IItem {
public double getUnitCost();
}
@Data
public class Item {
private String itemID;
private String title;
private String description;
private double cost;
public Item(String itemID, String title,
String description, double cost) {
this.itemID = itemID;
this.title = title;
this.description = description;
this.cost = cost;
System.out.println("create Item.");
}
public double getUnitCost(){
return cost;
}
}
在spring-prj2 中创建Spring 配置文件applicationContext.xml,并在其中使用构造器注入的方式配置Item 实例,具体代码如下
<?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-4.0.xsd">
<bean id="item1" class="cn.edu.zjut.bean.Item">
<constructor-arg index="0" type="java.lang.String">
<value>978-7-121-12345-1</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>JAVAEE 技术实验指导教程</value>
</constructor-arg>
<constructor-arg index="2" type="java.lang.String">
<value>WEB 程序设计知识回顾、轻量级JAVAEE 应用框架、企业级EJB 组
件编程技术、JAVAEE 综合应用开发</value>
</constructor-arg>
<constructor-arg index="3" type="double">
<value>19.95</value>
</constructor-arg>
</bean>
<bean id="item2" class="cn.edu.zjut.bean.Item">
<constructor-arg index="0" type="java.lang.String">
<value>978-7-121-12345-2</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>JAVAEE 技术</value>
</constructor-arg>
<constructor-arg index="2" type="java.lang.String">
<value>Struts 框架、Hibernate 框架、Spring 框架、会话Bean、实体
Bean、消息驱动Bean</value>
</constructor-arg>
<constructor-arg index="3" type="double">
<value>29.95</value>
</constructor-arg>
</bean>
</beans>
在spring-prj2 中新建cn.edu.zjut.app 包,并在其中创建测试类SpringEnvTest,对构造器注入进行测试,具体代码如下:
package cn.edu.zjut.app;
import cn.edu.zjut.bean.Item;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Item item1 = (Item) ctx.getBean("item1");
System.out.println(item1.getItemID());
System.out.println(item1.getTitle());
System.out.println(item1.getDescription());
System.out.println(item1.getCost());
Item item2 = (Item) ctx.getBean("item2");
System.out.println(item2.getItemID());
System.out.println(item2.getTitle());
System.out.println(item2.getDescription());
System.out.println(item2.getCost());
}
}
创建IItemOrder 接口
在spring-prj2 的cn.edu.zjut.bean 包中创建IItemOrder 接口及其实现类ItemOrder(代码片段如下);
package cn.edu.zjut.bean;
/**
* @Author: 张坤
* @DateTime: 2021/11/24 14:05
* @Description: 该类用于 TODO
*/
public interface IItemOrder {
public void incrementNumItems();
public void cancelOrder();
public double getTotalCost();
}
@Data
public class ItemOrder implements IItemOrder{
private Item item;
private int numItems;
public double getUnitCost(){
return 11.1;
}
@Override
public void incrementNumItems() {
setNumItems(getNumItems() + 1);
}
@Override
public void cancelOrder() {
setNumItems(0);
}
@Override
public double getTotalCost() {
return (getNumItems() * item.getUnitCost());
}
}@Data
public class ItemOrder implements IItemOrder{
private IItem item;
private int numItems;
public double getUnitCost(){
return 11.1;
}
public void incrementNumItems() {
setNumItems(getNumItems() + 1);
}
public void cancelOrder() {
setNumItems(0);
}
public double getTotalCost() {
return (getNumItems() * item.getUnitCost());
}
}
修改Spring 配置文件applicationContext.xml,在其中使用设置注入的方式增加ItemOrder 实例的配置,代码片段如下:
<bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder">
<property name="numItems"> <value>1</value> </property>
<property name="item"> <ref bean="item1"/> </property>
</bean>
<bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrder">
<property name="numItems"> <value>2</value> </property>
<property name="item"> <ref bean="item2"/> </property>
</bean>
查看输出如下:
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
ItemOrder itemorder1 = (ItemOrder)
ctx.getBean("itemorder1");
System.out.println("书名:" + (itemorder1).getItem().getTitle());
System.out.println("数量:" + (itemorder1).getNumItems());
ItemOrder itemorder2 = (ItemOrder)
ctx.getBean("itemorder2");
System.out.println("书名:" + (itemorder2).getItem().getTitle());
System.out.println("数量:" + (itemorder2).getNumItems());
}
}
二、提高实验——Spring 容器中的Bean
实验内容及步骤
添加作用域属性
修改Spring 配置文件applicationContext.xml,为Item 实例的配置添加作用域属性(scope),代码片段如下:
<bean id="item1" class="cn.edu.zjut.bean.Item" scope="singleton">
<constructor-arg index="0" type="java.lang.String" >
<value>978-7-121-12345-1</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>JAVAEE 技术实验指导教程</value>
</constructor-arg>
<constructor-arg index="2" type="java.lang.String">
<value>WEB 程序设计知识回顾、轻量级JAVAEE 应用框架、企业级EJB 组
件编程技术、JAVAEE 综合应用开发</value>
</constructor-arg>
<constructor-arg index="3" type="double">
<value>19.95</value>
</constructor-arg>
</bean>
<bean id="item2" class="cn.edu.zjut.bean.Item" scope="prototype">
<constructor-arg index="0" type="java.lang.String">
<value>978-7-121-12345-2</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>JAVAEE 技术</value>
</constructor-arg>
<constructor-arg index="2" type="java.lang.String">
<value>Struts 框架、Hibernate 框架、Spring 框架、会话Bean、实体
Bean、消息驱动Bean</value>
</constructor-arg>
<constructor-arg index="3" type="double">
<value>29.95</value>
</constructor-arg>
</bean>
修改测试类SpringEnvTest
修改测试类SpringEnvTest,对bean 的作用域进行测试,代码片段如下:
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("getBean(item1)---1");
IItem item11 = (IItem) ctx.getBean("item1");
System.out.println("getBean(item1)---2");
IItem item12 = (IItem) ctx.getBean("item1");
System.out.println("getBean(item2)---1");
IItem item21 = (IItem) ctx.getBean("item2");
System.out.println("getBean(item2)---2");
IItem item22 = (IItem) ctx.getBean("item2");
}
}
查看结果
运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果;
修改ItemOrder
修改cn.edu.zjut.bean 包中的ItemOrder.java,在其构造方法及setters 方法中添加相应的输出,代码片段如下:
public class ItemOrder implements IItemOrder, InitializingBean {
private Item item;
private int numItems;
public ItemOrder() {
System.out.println("Spring 实例化ItemOrder...");
}
public void setItem(Item item) {
System.out.println("Spring 注入item...");
this.item = item;
}
public void setNumItems(int n) {
System.out.println("Spring 注入numItems...");
this.numItems = n;
}
public double getUnitCost(){
return 11.1;
}
@Override
public void incrementNumItems() {
setNumItems(getNumItems() + 1);
}
@Override
public void cancelOrder() {
setNumItems(0);
}
@Override
public double getTotalCost() {
return (getNumItems() * item.getUnitCost());
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
修改测试类SpringEnvTest
修改测试类SpringEnvTest,对bean 的初始化方法进行测试,代码片段如下:
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("getBean(item1)---1");
IItemOrder itemorder1 = (IItemOrder)ctx.getBean("itemorder1");
}
}
查看结果
运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果
实现InitializingBean 接口
修改cn.edu.zjut.bean 包中的ItemOrder.java,通过实现InitializingBean 接口的方式,添加bean 的依赖关系注入之后的行为,代码片段如下:
public class ItemOrder implements IItemOrder, InitializingBean {
public void afterPropertiesSet() throws Exception {
System.out.println("正在执行初始化方法afterPropertiesSet...");
}
}
init-method
修改cn.edu.zjut.bean 包中的ItemOrder.java,通过自定义方法,添加bean 的依赖关系注入之后的行为,代码片段如下:
public class ItemOrder implements IItemOrder, InitializingBean {
...
public void init() {
System.out.println("正在执行初始化方法init...");
}
}
修改Spring 配置文件applicationContext.xml,通过使用init-method 属性的方式,为ItemOrder 实例添加bean 的依赖关系注入之后的行为,代码片段如下:
<bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder" init-method="init">
<property name="numItems"> <value>1</value> </property>
<property name="item"> <ref bean="item1"/> </property>
</bean>
destroy-method
实现接口方式
修改cn.edu.zjut.bean 包中的ItemOrder.java,通过实现DisposableBean 接口的方式,添加bean 销毁之前的行为(代码略);
public class ItemOrder implements IItemOrder, InitializingBean , DisposableBean {
@Override
public void destroy(){
System.out.println("正在准备执行销毁方法destroy...");
}
}
手动关闭容器
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("getBean(item1)---1");
IItemOrder itemorder1 = (IItemOrder)ctx.getBean("itemorder1");
((AbstractApplicationContext)ctx).registerShutdownHook();
}
}
修改xml配置方式
修改cn.edu.zjut.bean 包中的ItemOrder.java,通过自定义方法,添加bean销毁之前的行为;并修改Spring 配置文件applicationContext.xml,通过使用destroy-method 属性的方式,为ItemOrder 实例添加bean 销毁之前
的行为;
<bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder" init-method="init" destroy-method="destroy">
<property name="numItems"> <value>1</value> </property>
<property name="item"> <ref bean="item1"/> </property>
</bean>
静态工厂
在工程spring-prj2 的cn.edu.zjut.bean 包中创建工厂类ItemOrderFactory.java,并在类中提供静态工厂方法返回ItemOrder 实例,具体代码如下:
public class ItemOrderFactory {
public static ItemOrder createItemOrder() {
System.out.println("调用静态工厂方法创建bean...");
return new ItemOrder();
}
}
修改Spring 配置文件applicationContext.xml,使用factory-method 属性调用静态工厂方法,创建ItemOrder 实例,代码片段如下:
<bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrderFactory"
factory-method="createItemOrder">
<property name="numItems"> <value>1</value> </property>
<property name="item"> <ref bean="item1"/> </property>
</bean>
实例工厂
修改工厂类ItemOrderFactory.java,将其中的静态工厂方法修改为实例工厂方法,具体代码如下:
public class ItemOrderFactory {
public ItemOrder createItemOrder() {
System.out.println("调用实例工厂方法创建bean...");
return new ItemOrder();
}
}
修改Spring 配置文件applicationContext.xml,使用factory-method 属性和factory-bean 属性调用实例工厂方法,创建ItemOrder 实例,代码片段如下
<bean id="itemorderFactory"
class="cn.edu.zjut.bean.ItemOrderFactory"/>
<bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrder"
factory-method="createItemOrder"
factory-bean="itemorderFactory">
<property name="numItems"> <value>1</value> </property>
<property name="item"> <ref bean="item1"/> </property>
</bean>
三、扩展实验——深入Spring 容器
实验内容及步骤
不同的实例创建方法
修改测试类SpringEnvTest,分别使用XmlBeanFactory 创建BeanFactory 实例,或使FileSystemXmlApplicationContext、ClassPathXmlApplicationContext 创建ApplicationContext 实例,代码片段如下:
public class SpringEnvTest {
public static void main(String[] args) {
FileSystemResource isr = new
FileSystemResource("src/applicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(isr);
IItemOrder itemorder3 = (IItemOrder)
factory.getBean("itemorder3");
}
}
运行不了
public class SpringEnvTest {
public static void main(String[] args) {
ClassPathResource res = new
ClassPathResource("applicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
IItemOrder itemorder3 = (IItemOrder)
factory.getBean("itemorder2");
}
}
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
IItemOrder itemorder3 = (IItemOrder)ctx.getBean("itemorder2");
}
}
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"applicationContext.xml");
IItemOrder itemorder3 = (IItemOrder)ctx.getBean("itemorder2");
}
}
国际化
在spring-prj2 中新建cn.edu.zjut.local 包,并在其中创建简体中文的资源文件:message_zh_CN.properties,在其中输入“HelloWorld={0},现在是{1}” ,并对其进行转码,最终得到
HelloWorld={0},\u73b0\u5728\u662f{1}
在cn.edu.zjut.local 包中创建美式英语的资源文件:message_en_US.properties,具体代码如下:
HelloWorld={0},now is{1}
两个文件的位置均在resource下
修改Spring 配置文件applicationContext.xml,增加名为messageSource 的bean实例以完成国际化的配置,代码片段如下:
<bean id="messageSource" class=
"org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>cn.edu.zjut.local.message</value>
<!-- 如果有多个资源文件,全部列在此处-->
</list>
</property>
</bean>
转码方式如下:
打开jdk目录下的bin,找到native2ascii.exe文件,双击执行
修改测试类SpringEnvTest,对ApplicationContext 对国际化的支持进行测试,代码片段如下:
修改测试类SpringEnvTest,将其中的“Locale.CHINA”替换成“Locale.US”,运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果;
spring事件
导入maven包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
在spring-prj2 中新建cn.edu.zjut.event 包,并在其中创建Spring 容器事件类,并继承ApplicationEvent 类,具体代码如下:
@Data
public class EmailEvent extends ApplicationEvent {
private String address;
private String text;
public EmailEvent(Object source){
super(source);
}
public EmailEvent(Object source, String address, String text){
super(source);
this.setAddress(address);
this.setText(text);
}
}
在spring-prj2 中新建cn.edu.zjut.listener 包,并在其中创建Spring 容器事件的监听器类,并实现ApplicationListener 接口,具体代码如下:
class EmailNotifier implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent evt){
if(evt instanceof EmailEvent){
EmailEvent emailEvent = (EmailEvent)evt;
System.out.println("需要发送邮件的接收地址" +
emailEvent.getAddress());
System.out.println("需要发送邮件的邮件正文" +
emailEvent.getText());
}else{
System.out.println("容器本身的事件" + evt);
}
}
}
修改Spring 配置文件applicationContext.xml,Spring 容器事件注册监听器,代码片段如下:
<bean class="cn.edu.zjut.listener.EmailNotifier"/>
修改测试类SpringEnvTest,调用ApplicationContext 的publishEvent 来触发事件,代码片段如下:
public class SpringEnvTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
EmailEvent ele = new EmailEvent("hello", "spring_test@zjut.edu.cn", "this is a test");
ctx.publishEvent(ele);
}
}