浙江工业大学logo-文字.png

JavaEE实验
2021/2022(1)
浙江工业大学logo.png

  1. 实验9 spring-prj2

学生姓名 张坤
学生学号 201906061726
学生班级 软件工程1903
任课教师 韩珊珊
提交日期 2021年12月2日

计算机科学与技术学院

一、基础实验——Spring 容器中的依赖注入

实验内容及步骤

新建项目

image.pngimage.png
选择普通的maven项目,命名后默认配置即可

导入maven包

  1. <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-core</artifactId>
  5. <version>5.3.8</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework</groupId>
  9. <artifactId>spring-context</artifactId>
  10. <version>5.3.8</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-beans</artifactId>
  15. <version>5.3.8</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-expression</artifactId>
  20. <version>5.3.8</version>
  21. </dependency>

搭建spring框架

在spring-prj2 中新建cn.edu.zjut.bean 包,并在其中创建IItem 接口(代码略)及其实现类Item(代码片段如下);

  1. public interface IItem {
  2. public double getUnitCost();
  3. }
  1. @Data
  2. public class Item {
  3. private String itemID;
  4. private String title;
  5. private String description;
  6. private double cost;
  7. public Item(String itemID, String title,
  8. String description, double cost) {
  9. this.itemID = itemID;
  10. this.title = title;
  11. this.description = description;
  12. this.cost = cost;
  13. System.out.println("create Item.");
  14. }
  15. public double getUnitCost(){
  16. return cost;
  17. }
  18. }

在spring-prj2 中创建Spring 配置文件applicationContext.xml,并在其中使用构造器注入的方式配置Item 实例,具体代码如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
  7. <bean id="item1" class="cn.edu.zjut.bean.Item">
  8. <constructor-arg index="0" type="java.lang.String">
  9. <value>978-7-121-12345-1</value>
  10. </constructor-arg>
  11. <constructor-arg index="1" type="java.lang.String">
  12. <value>JAVAEE 技术实验指导教程</value>
  13. </constructor-arg>
  14. <constructor-arg index="2" type="java.lang.String">
  15. <value>WEB 程序设计知识回顾、轻量级JAVAEE 应用框架、企业级EJB 组
  16. 件编程技术、JAVAEE 综合应用开发</value>
  17. </constructor-arg>
  18. <constructor-arg index="3" type="double">
  19. <value>19.95</value>
  20. </constructor-arg>
  21. </bean>
  22. <bean id="item2" class="cn.edu.zjut.bean.Item">
  23. <constructor-arg index="0" type="java.lang.String">
  24. <value>978-7-121-12345-2</value>
  25. </constructor-arg>
  26. <constructor-arg index="1" type="java.lang.String">
  27. <value>JAVAEE 技术</value>
  28. </constructor-arg>
  29. <constructor-arg index="2" type="java.lang.String">
  30. <value>Struts 框架、Hibernate 框架、Spring 框架、会话Bean、实体
  31. Bean、消息驱动Bean</value>
  32. </constructor-arg>
  33. <constructor-arg index="3" type="double">
  34. <value>29.95</value>
  35. </constructor-arg>
  36. </bean>
  37. </beans>

在spring-prj2 中新建cn.edu.zjut.app 包,并在其中创建测试类SpringEnvTest,对构造器注入进行测试,具体代码如下:

  1. package cn.edu.zjut.app;
  2. import cn.edu.zjut.bean.Item;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class SpringEnvTest {
  6. public static void main(String[] args) {
  7. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  8. "applicationContext.xml");
  9. Item item1 = (Item) ctx.getBean("item1");
  10. System.out.println(item1.getItemID());
  11. System.out.println(item1.getTitle());
  12. System.out.println(item1.getDescription());
  13. System.out.println(item1.getCost());
  14. Item item2 = (Item) ctx.getBean("item2");
  15. System.out.println(item2.getItemID());
  16. System.out.println(item2.getTitle());
  17. System.out.println(item2.getDescription());
  18. System.out.println(item2.getCost());
  19. }
  20. }

输出如下:
image.png

创建IItemOrder 接口

在spring-prj2 的cn.edu.zjut.bean 包中创建IItemOrder 接口及其实现类ItemOrder(代码片段如下);

  1. package cn.edu.zjut.bean;
  2. /**
  3. * @Author: 张坤
  4. * @DateTime: 2021/11/24 14:05
  5. * @Description: 该类用于 TODO
  6. */
  7. public interface IItemOrder {
  8. public void incrementNumItems();
  9. public void cancelOrder();
  10. public double getTotalCost();
  11. }
  1. @Data
  2. public class ItemOrder implements IItemOrder{
  3. private Item item;
  4. private int numItems;
  5. public double getUnitCost(){
  6. return 11.1;
  7. }
  8. @Override
  9. public void incrementNumItems() {
  10. setNumItems(getNumItems() + 1);
  11. }
  12. @Override
  13. public void cancelOrder() {
  14. setNumItems(0);
  15. }
  16. @Override
  17. public double getTotalCost() {
  18. return (getNumItems() * item.getUnitCost());
  19. }
  20. }@Data
  21. public class ItemOrder implements IItemOrder{
  22. private IItem item;
  23. private int numItems;
  24. public double getUnitCost(){
  25. return 11.1;
  26. }
  27. public void incrementNumItems() {
  28. setNumItems(getNumItems() + 1);
  29. }
  30. public void cancelOrder() {
  31. setNumItems(0);
  32. }
  33. public double getTotalCost() {
  34. return (getNumItems() * item.getUnitCost());
  35. }
  36. }

修改Spring 配置文件applicationContext.xml,在其中使用设置注入的方式增加ItemOrder 实例的配置,代码片段如下:

  1. <bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder">
  2. <property name="numItems"> <value>1</value> </property>
  3. <property name="item"> <ref bean="item1"/> </property>
  4. </bean>
  5. <bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrder">
  6. <property name="numItems"> <value>2</value> </property>
  7. <property name="item"> <ref bean="item2"/> </property>
  8. </bean>

查看输出如下:

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. ItemOrder itemorder1 = (ItemOrder)
  6. ctx.getBean("itemorder1");
  7. System.out.println("书名:" + (itemorder1).getItem().getTitle());
  8. System.out.println("数量:" + (itemorder1).getNumItems());
  9. ItemOrder itemorder2 = (ItemOrder)
  10. ctx.getBean("itemorder2");
  11. System.out.println("书名:" + (itemorder2).getItem().getTitle());
  12. System.out.println("数量:" + (itemorder2).getNumItems());
  13. }
  14. }

image.png

二、提高实验——Spring 容器中的Bean

实验内容及步骤

添加作用域属性

修改Spring 配置文件applicationContext.xml,为Item 实例的配置添加作用域属性(scope),代码片段如下:

  1. <bean id="item1" class="cn.edu.zjut.bean.Item" scope="singleton">
  2. <constructor-arg index="0" type="java.lang.String" >
  3. <value>978-7-121-12345-1</value>
  4. </constructor-arg>
  5. <constructor-arg index="1" type="java.lang.String">
  6. <value>JAVAEE 技术实验指导教程</value>
  7. </constructor-arg>
  8. <constructor-arg index="2" type="java.lang.String">
  9. <value>WEB 程序设计知识回顾、轻量级JAVAEE 应用框架、企业级EJB 组
  10. 件编程技术、JAVAEE 综合应用开发</value>
  11. </constructor-arg>
  12. <constructor-arg index="3" type="double">
  13. <value>19.95</value>
  14. </constructor-arg>
  15. </bean>
  16. <bean id="item2" class="cn.edu.zjut.bean.Item" scope="prototype">
  17. <constructor-arg index="0" type="java.lang.String">
  18. <value>978-7-121-12345-2</value>
  19. </constructor-arg>
  20. <constructor-arg index="1" type="java.lang.String">
  21. <value>JAVAEE 技术</value>
  22. </constructor-arg>
  23. <constructor-arg index="2" type="java.lang.String">
  24. <value>Struts 框架、Hibernate 框架、Spring 框架、会话Bean、实体
  25. Bean、消息驱动Bean</value>
  26. </constructor-arg>
  27. <constructor-arg index="3" type="double">
  28. <value>29.95</value>
  29. </constructor-arg>
  30. </bean>

修改测试类SpringEnvTest

修改测试类SpringEnvTest,对bean 的作用域进行测试,代码片段如下:

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. System.out.println("getBean(item1)---1");
  6. IItem item11 = (IItem) ctx.getBean("item1");
  7. System.out.println("getBean(item1)---2");
  8. IItem item12 = (IItem) ctx.getBean("item1");
  9. System.out.println("getBean(item2)---1");
  10. IItem item21 = (IItem) ctx.getBean("item2");
  11. System.out.println("getBean(item2)---2");
  12. IItem item22 = (IItem) ctx.getBean("item2");
  13. }
  14. }

查看结果

运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果;
image.png

修改ItemOrder

修改cn.edu.zjut.bean 包中的ItemOrder.java,在其构造方法及setters 方法中添加相应的输出,代码片段如下:

  1. public class ItemOrder implements IItemOrder, InitializingBean {
  2. private Item item;
  3. private int numItems;
  4. public ItemOrder() {
  5. System.out.println("Spring 实例化ItemOrder...");
  6. }
  7. public void setItem(Item item) {
  8. System.out.println("Spring 注入item...");
  9. this.item = item;
  10. }
  11. public void setNumItems(int n) {
  12. System.out.println("Spring 注入numItems...");
  13. this.numItems = n;
  14. }
  15. public double getUnitCost(){
  16. return 11.1;
  17. }
  18. @Override
  19. public void incrementNumItems() {
  20. setNumItems(getNumItems() + 1);
  21. }
  22. @Override
  23. public void cancelOrder() {
  24. setNumItems(0);
  25. }
  26. @Override
  27. public double getTotalCost() {
  28. return (getNumItems() * item.getUnitCost());
  29. }
  30. @Override
  31. public void afterPropertiesSet() throws Exception {
  32. }
  33. }

修改测试类SpringEnvTest

修改测试类SpringEnvTest,对bean 的初始化方法进行测试,代码片段如下:

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. System.out.println("getBean(item1)---1");
  6. IItemOrder itemorder1 = (IItemOrder)ctx.getBean("itemorder1");
  7. }
  8. }

查看结果

运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果
image.png

实现InitializingBean 接口

修改cn.edu.zjut.bean 包中的ItemOrder.java,通过实现InitializingBean 接口的方式,添加bean 的依赖关系注入之后的行为,代码片段如下:

  1. public class ItemOrder implements IItemOrder, InitializingBean {
  2. public void afterPropertiesSet() throws Exception {
  3. System.out.println("正在执行初始化方法afterPropertiesSet...");
  4. }
  5. }

查看结果
image.png

init-method

修改cn.edu.zjut.bean 包中的ItemOrder.java,通过自定义方法,添加bean 的依赖关系注入之后的行为,代码片段如下:

  1. public class ItemOrder implements IItemOrder, InitializingBean {
  2. ...
  3. public void init() {
  4. System.out.println("正在执行初始化方法init...");
  5. }
  6. }

修改Spring 配置文件applicationContext.xml,通过使用init-method 属性的方式,为ItemOrder 实例添加bean 的依赖关系注入之后的行为,代码片段如下:

  1. <bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder" init-method="init">
  2. <property name="numItems"> <value>1</value> </property>
  3. <property name="item"> <ref bean="item1"/> </property>
  4. </bean>

image.png

destroy-method

实现接口方式

修改cn.edu.zjut.bean 包中的ItemOrder.java,通过实现DisposableBean 接口的方式,添加bean 销毁之前的行为(代码略);

  1. public class ItemOrder implements IItemOrder, InitializingBean , DisposableBean {
  2. @Override
  3. public void destroy(){
  4. System.out.println("正在准备执行销毁方法destroy...");
  5. }
  6. }

手动关闭容器

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. System.out.println("getBean(item1)---1");
  6. IItemOrder itemorder1 = (IItemOrder)ctx.getBean("itemorder1");
  7. ((AbstractApplicationContext)ctx).registerShutdownHook();
  8. }
  9. }

查看结果
image.png

修改xml配置方式

修改cn.edu.zjut.bean 包中的ItemOrder.java,通过自定义方法,添加bean销毁之前的行为;并修改Spring 配置文件applicationContext.xml,通过使用destroy-method 属性的方式,为ItemOrder 实例添加bean 销毁之前
的行为;

  1. <bean id="itemorder1" class="cn.edu.zjut.bean.ItemOrder" init-method="init" destroy-method="destroy">
  2. <property name="numItems"> <value>1</value> </property>
  3. <property name="item"> <ref bean="item1"/> </property>
  4. </bean>

image.png

静态工厂

在工程spring-prj2 的cn.edu.zjut.bean 包中创建工厂类ItemOrderFactory.java,并在类中提供静态工厂方法返回ItemOrder 实例,具体代码如下:

  1. public class ItemOrderFactory {
  2. public static ItemOrder createItemOrder() {
  3. System.out.println("调用静态工厂方法创建bean...");
  4. return new ItemOrder();
  5. }
  6. }

修改Spring 配置文件applicationContext.xml,使用factory-method 属性调用静态工厂方法,创建ItemOrder 实例,代码片段如下:

  1. <bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrderFactory"
  2. factory-method="createItemOrder">
  3. <property name="numItems"> <value>1</value> </property>
  4. <property name="item"> <ref bean="item1"/> </property>
  5. </bean>

image.png

实例工厂

修改工厂类ItemOrderFactory.java,将其中的静态工厂方法修改为实例工厂方法,具体代码如下:

  1. public class ItemOrderFactory {
  2. public ItemOrder createItemOrder() {
  3. System.out.println("调用实例工厂方法创建bean...");
  4. return new ItemOrder();
  5. }
  6. }

修改Spring 配置文件applicationContext.xml,使用factory-method 属性和factory-bean 属性调用实例工厂方法,创建ItemOrder 实例,代码片段如下

  1. <bean id="itemorderFactory"
  2. class="cn.edu.zjut.bean.ItemOrderFactory"/>
  3. <bean id="itemorder2" class="cn.edu.zjut.bean.ItemOrder"
  4. factory-method="createItemOrder"
  5. factory-bean="itemorderFactory">
  6. <property name="numItems"> <value>1</value> </property>
  7. <property name="item"> <ref bean="item1"/> </property>
  8. </bean>

image.png

三、扩展实验——深入Spring 容器

实验内容及步骤

不同的实例创建方法

修改测试类SpringEnvTest,分别使用XmlBeanFactory 创建BeanFactory 实例,或使FileSystemXmlApplicationContext、ClassPathXmlApplicationContext 创建ApplicationContext 实例,代码片段如下:

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. FileSystemResource isr = new
  4. FileSystemResource("src/applicationContext.xml");
  5. XmlBeanFactory factory = new XmlBeanFactory(isr);
  6. IItemOrder itemorder3 = (IItemOrder)
  7. factory.getBean("itemorder3");
  8. }
  9. }

运行不了

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ClassPathResource res = new
  4. ClassPathResource("applicationContext.xml");
  5. XmlBeanFactory factory = new XmlBeanFactory(res);
  6. IItemOrder itemorder3 = (IItemOrder)
  7. factory.getBean("itemorder2");
  8. }
  9. }

image.png

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. IItemOrder itemorder3 = (IItemOrder)ctx.getBean("itemorder2");
  6. }
  7. }

image.png

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new FileSystemXmlApplicationContext(
  4. "applicationContext.xml");
  5. IItemOrder itemorder3 = (IItemOrder)ctx.getBean("itemorder2");
  6. }
  7. }

运行不了

国际化

在spring-prj2 中新建cn.edu.zjut.local 包,并在其中创建简体中文的资源文件:message_zh_CN.properties,在其中输入“HelloWorld={0},现在是{1}” ,并对其进行转码,最终得到

  1. HelloWorld={0},\u73b0\u5728\u662f{1}

在cn.edu.zjut.local 包中创建美式英语的资源文件:message_en_US.properties,具体代码如下:

  1. HelloWorld={0},now is{1}

两个文件的位置均在resource下
image.png
修改Spring 配置文件applicationContext.xml,增加名为messageSource 的bean实例以完成国际化的配置,代码片段如下:

  1. <bean id="messageSource" class=
  2. "org.springframework.context.support.ResourceBundleMessageSource">
  3. <property name="basenames">
  4. <list>
  5. <value>cn.edu.zjut.local.message</value>
  6. <!-- 如果有多个资源文件,全部列在此处-->
  7. </list>
  8. </property>
  9. </bean>

转码方式如下:
打开jdk目录下的bin,找到native2ascii.exe文件,双击执行
image.png
修改测试类SpringEnvTest,对ApplicationContext 对国际化的支持进行测试,代码片段如下:
image.png
修改测试类SpringEnvTest,将其中的“Locale.CHINA”替换成“Locale.US”,运行测试类SpringEnvTest,观察控制台的输出,并记录运行结果;
image.png

spring事件

导入maven包

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-aop</artifactId>
  4. <version>4.3.12.RELEASE</version>
  5. </dependency>

在spring-prj2 中新建cn.edu.zjut.event 包,并在其中创建Spring 容器事件类,并继承ApplicationEvent 类,具体代码如下:

  1. @Data
  2. public class EmailEvent extends ApplicationEvent {
  3. private String address;
  4. private String text;
  5. public EmailEvent(Object source){
  6. super(source);
  7. }
  8. public EmailEvent(Object source, String address, String text){
  9. super(source);
  10. this.setAddress(address);
  11. this.setText(text);
  12. }
  13. }

在spring-prj2 中新建cn.edu.zjut.listener 包,并在其中创建Spring 容器事件的监听器类,并实现ApplicationListener 接口,具体代码如下:

  1. class EmailNotifier implements ApplicationListener {
  2. @Override
  3. public void onApplicationEvent(ApplicationEvent evt){
  4. if(evt instanceof EmailEvent){
  5. EmailEvent emailEvent = (EmailEvent)evt;
  6. System.out.println("需要发送邮件的接收地址" +
  7. emailEvent.getAddress());
  8. System.out.println("需要发送邮件的邮件正文" +
  9. emailEvent.getText());
  10. }else{
  11. System.out.println("容器本身的事件" + evt);
  12. }
  13. }
  14. }

修改Spring 配置文件applicationContext.xml,Spring 容器事件注册监听器,代码片段如下:

  1. <bean class="cn.edu.zjut.listener.EmailNotifier"/>

修改测试类SpringEnvTest,调用ApplicationContext 的publishEvent 来触发事件,代码片段如下:

  1. public class SpringEnvTest {
  2. public static void main(String[] args) {
  3. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  4. "applicationContext.xml");
  5. EmailEvent ele = new EmailEvent("hello", "spring_test@zjut.edu.cn", "this is a test");
  6. ctx.publishEvent(ele);
  7. }
  8. }

image.png