Spring管理Bean-IOC-03

2.基于XML配置bean

2.15bean的生命周期

bean对象的创建是由JVM完成的,然后执行如下方法:

  1. 执行构造器
  2. 执行set相关方法
  3. 调用bean的初始化方法(需要配置)
  4. 使用bean
  5. 容器关闭时,调用bean的销毁方法(需要配置)

例子

House:

  1. package com.li.bean;
  2. /**
  3. * @author 李
  4. * @version 1.0
  5. */
  6. public class House {
  7. private String name;
  8. public House() {
  9. System.out.println("House() 构造器被执行...");
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. System.out.println("House setName()=" + name);
  16. this.name = name;
  17. }
  18. //说明:初始化方法是自定义的,名字随意,只要配置的时候指定名称就行了
  19. public void init() {
  20. System.out.println("House init() 被执行...");
  21. }
  22. //说明:销毁的方法是也自定义的,名字随意
  23. public void destroy() {
  24. System.out.println("House destroy() 被执行...");
  25. }
  26. }

beans.xml:

  1. <!--配置House对象,演示bean的生命周期
  2. 1.init-method 指定bean的初始化方法,该方法在bean执行setter方法后执行
  3. 2.init-method指定方法执行的时机,由spring容器来控制
  4. 3.destroy-method 指定bean的销毁方法,该方法在容器关闭的时候被执行
  5. 4.destroy-method指定方法执行的时机,也是由spring容器来控制
  6. -->
  7. <bean class="com.li.bean.House" id="house"
  8. init-method="init"
  9. destroy-method="destroy">
  10. <property name="name" value="北京大豪宅"/>
  11. </bean>

测试方法:

  1. //测试bean的生命周期
  2. @Test
  3. public void testBeanLife() {
  4. ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
  5. House house = ioc.getBean("house", House.class);
  6. System.out.println("使用house=" + house);
  7. //关闭容器
  8. // 1.ioc的编译类型 ApplicationContext ,运行类型 ClassPathXmlApplicationContext
  9. // 2.因为 ClassPathXmlApplicationContext 实现了接口 ConfigurableApplicationContext
  10. // 3.而ConfigurableApplicationContext接口有 close方法
  11. // 4.因此将ioc转成 ConfigurableApplicationContext 类型,调用close方法,关闭容器
  12. ((ConfigurableApplicationContext)ioc).close();
  13. }

使用细节:

  1. 初始化方法和销毁方法有程序员自定义
  2. 销毁方法只有当关闭容器时才会被调用

2.16配置bean的后置处理器

  1. 在spring的ioc容器,可以配置bean的后置处理器(后置处理器其实就是一个java对象)
  2. 该处理器会在bean 初始化方法调用前 和 初始化方法调用后 被调用
  3. 程序员可以在后置处理器中编写自己的业务代码

例子

1.House类(见2.15),该方法设置了构造函数,bean初始化方法等

2.创建后置处理器:MyBeanPostProcessor:

后置处理器需要实现BeanPostProcessor接口,该接口中有两个重要的方法,对应我们之前说的 “初始化方法调用前 和 初始化方法调用后 被调用”

  1. package com.li.bean;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.config.BeanPostProcessor;
  4. /**
  5. * @author 李
  6. * @version 1.0
  7. * 这是一个后置处理器,必须实现接口 BeanPostProcessor
  8. */
  9. public class MyBeanPostProcessor implements BeanPostProcessor {
  10. /**
  11. * 调用时机:在Bean初始化方法前被调用(bean没有配置初始化方法,此方法也会被调用)
  12. *
  13. * @param bean 传入 在IOC容器中创建/配置的Bean
  14. * @param beanName 在IOC容器中创建/配置的Bean的id
  15. * @return Object 返回 bean(返回前程序员可以对bean进行修改/处理,再返回)
  16. * @throws BeansException
  17. */
  18. @Override
  19. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  20. System.out.println("postProcessBeforeInitialization()被调用..." +
  21. "bean=" + bean + " beanName=" + beanName);
  22. return bean;
  23. }
  24. /**
  25. * 调用时机:在Bean初始化方法后被调用(bean没有配置初始化方法,此方法也会被调用)
  26. *
  27. * @param bean 传入 在IOC容器中创建/配置的Bean
  28. * @param beanName 在IOC容器中创建/配置的Bean的id
  29. * @return Object 返回 bean(返回前程序员可以对bean进行修改/处理,再返回)
  30. * @throws BeansException
  31. */
  32. @Override
  33. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  34. System.out.println("postProcessAfterInitialization()被调用..." +
  35. "bean=" + bean + " beanName=" + beanName);
  36. return bean;
  37. }
  38. }

3.beans02.xml:

因为后置处理器对象会作用在容器配置文件的所有bean对象中,因此这里新创建一个容器文件beans02.xml,为了输出干净,该配置文件中只配置了house一个bean对象

  1. <!--配置House对象-->
  2. <bean class="com.li.bean.House" id="house"
  3. init-method="init" destroy-method="destroy">
  4. <property name="name" value="海景大豪宅"/>
  5. </bean>
  6. <!--配置后置处理器对象
  7. 1.当我们在beans02.xml容器配置文件 配置了MyBeanPostProcessor后
  8. 2.该后置处理器对象,就会作用在该容器文件的所有Bean对象中
  9. -->
  10. <bean class="com.li.bean.MyBeanPostProcessor" id="myBeanPostProcessor"/>

4.测试方法:

  1. //测试bean的后置处理器
  2. @Test
  3. public void testBeanPostProcessor() {
  4. ApplicationContext ioc = new ClassPathXmlApplicationContext("beans02.xml");
  5. House house = ioc.getBean("house", House.class);
  6. System.out.println("使用house=" + house);
  7. //关闭容器
  8. ((ClassPathXmlApplicationContext)ioc).close();
  9. }

细节说明:

  1. 怎么执行到这个方法?==>使用AOP(反射+动态代理+IO+容器+注解)
  2. 有什么用?==>可以对IOC容器中所有对象进行统一处理,如:日志处理/权限校验/安全的验证/事务管理
  3. 针对容器的所有对象吗? 是的=>切面编程特点

后置处理器是一个比较难理解的知识点,后面会实现这个机制,深入理解

2.17通过属性文件给bean注入值

在spring的ioc容器中,可以通过属性文件给bean注入值

例子

1.在src目录下创建my.properties文件

  1. monsterId=1000
  2. name=jack
  3. skill=hello

2.在beans.xml中配置:

  1. <!--指定属性文件
  2. 1.注意要引入命名空间才能使用
  3. 2.location="classpath:my.properties" 表示指定属性文件的位置
  4. (注意需要带上"classpath")
  5. 3.这时我们的属性值通过${属性名} 获取
  6. 4.这里的属性名就是my.properties中的 key
  7. -->
  8. <context:property-placeholder location="classpath:my.properties"/>
  9. <!--配置Monster对象
  10. 通过属性文件给Monster对象赋值-->
  11. <bean class="com.li.bean.Monster" id="monster1000">
  12. <property name="monsterId" value="${monsterId}"/>
  13. <property name="name" value="${name}"/>
  14. <property name="skill" value="${skill}"/>
  15. </bean>

3.测试:

  1. //通过属性文件给bean属性赋值
  2. @Test
  3. public void setBeanByFile() {
  4. ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
  5. Monster monster1000 = ioc.getBean("monster1000", Monster.class);
  6. System.out.println("monster1000=" + monster1000);
  7. }

注意:如果properties文件中的value是中文,会出现乱码,需要将中文转为unicode编码

2.18基于XML的bean自动装配

在spring的ioc容器中,可以实现自动装配bean

例子

1.OrderDAO

  1. package com.li.dao;
  2. /**
  3. * @author 李
  4. * @version 1.0
  5. * 这是一个DAO类
  6. */
  7. public class OrderDAO {
  8. public void saveOrder() {
  9. System.out.println("保存一个订单...");
  10. }
  11. }

2.OrderService

  1. package com.li.service;
  2. import com.li.dao.OrderDAO;
  3. /**
  4. * @author 李
  5. * @version 1.0
  6. * 这是一个Service类
  7. */
  8. public class OrderService {
  9. //OrderDAO属性
  10. private OrderDAO orderDAO;
  11. //getter
  12. public OrderDAO getOrderDAO() {
  13. return orderDAO;
  14. }
  15. //setter
  16. public void setOrderDAO(OrderDAO orderDAO) {
  17. this.orderDAO = orderDAO;
  18. }
  19. }

3.OrderServlet:

  1. package com.li.web;
  2. import com.li.service.OrderService;
  3. /**
  4. * @author 李
  5. * @version 1.0
  6. * Servlet即 Controller
  7. */
  8. public class OrderServlet {
  9. //属性OrderService
  10. private OrderService orderService;
  11. //getter
  12. public OrderService getOrderService() {
  13. return orderService;
  14. }
  15. //setter
  16. public void setOrderService(OrderService orderService) {
  17. this.orderService = orderService;
  18. }
  19. }

4.beans.xml:

  • autowire="byType"方式
  1. <!--配置OrderDAO对象-->
  2. <bean class="com.li.dao.OrderDAO" id="orderDAO"/>
  3. <!--配置OrderService对象
  4. 1. 属性 autowire="byType" 表示在创建OrderService时,
  5. 通过类型的方式,给对象的属性自动完成赋值/引用
  6. 2. 比如OrderService对象有private OrderDAO属性,就会在容器中找有没有OrderDAO类型的对象
  7. 如果有,就会自动进行装配(按照类型的方式来装配时,那么该容器中不能有超过一个OrderService对象)
  8. -->
  9. <bean autowire="byType" class="com.li.service.OrderService" id="orderService"/>
  10. <!--配置OrderServlet对象,同理-->
  11. <bean autowire="byType" class="com.li.web.OrderServlet" id="orderServlet"/>
  • 使用autowire="byName"方式
  1. <!--配置OrderDAO对象-->
  2. <bean class="com.li.dao.OrderDAO" id="orderDAO"/>
  3. <!--配置OrderService对象
  4. 3.如果设置的是 autowire="byName" 表示通过名字完成自动装配
  5. 比如下面的 autowire=" byName" class="com.li.service.OrderService"
  6. (1)spring会按照 OrderService对象的属性(如orderDAO)
  7. (2)找到这个属性的setXxx()方法的Xxx名称,在容器中找到相同id的对象来进行自动装配
  8. (3)例如我们的orderService对象中有一个setOrderDAO(),就会找id="orderDAO"的对象来进行自动装配
  9. (4)如果没有就装配失败
  10. -->
  11. <bean autowire="byName" class="com.li.service.OrderService" id="orderService"/>
  12. <!--配置OrderServlet对象,同理-->
  13. <bean autowire="byName" class="com.li.web.OrderServlet" id="orderServlet"/>

注意:这里不是通过对象的属性名来找的,而是setXxx方法的名称来找的,因为底层是反射实现的

因此如果对象的属性的setXxx方法的名称改变了,被自动装配的对象id也要随之改变

5.测试类:

  1. //基于XML的bean自动装配
  2. @Test
  3. public void setBeanByAutowire() {
  4. ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
  5. OrderServlet orderServlet = ioc.getBean("orderServlet", OrderServlet.class);
  6. //验证是否自动装配上了OrderService
  7. System.out.println(orderServlet.getOrderService());
  8. //验证是否自动装配上了OrderDAO
  9. System.out.println(orderServlet.getOrderService().getOrderDAO());
  10. }

可以看到orderServlet的orderService属性,以及属性的属性orderDAO成功装载了:(autowire="byType"/"byName"方式)

2.19Spring EL表达式

非重点,了解即可

  1. Spring Expression Language,Spring表达式语言,简称SpEL。支持运行时查询并可以操作对象。
  2. 和 JSP的EL表达式一样,SpEL根据Javabean风格的getXxx()、setXxx()方法定义的属性访问对象
  3. SpEL使用#{}作为定界符,所有在大括号中的字符都将被认为是SpEL表达式

应用实例

SpELBean:

  1. package com.li.bean;
  2. /**
  3. * @author 李
  4. * @version 1.0
  5. */
  6. public class SpELBean {
  7. private String name;
  8. private Monster monster;
  9. private String monsterName;
  10. private String crySound;
  11. private String bookName;
  12. private Double result;
  13. public SpELBean() {
  14. }
  15. public String getName() {
  16. return name;
  17. }
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. public Monster getMonster() {
  22. return monster;
  23. }
  24. public void setMonster(Monster monster) {
  25. this.monster = monster;
  26. }
  27. public String getMonsterName() {
  28. return monsterName;
  29. }
  30. public void setMonsterName(String monsterName) {
  31. this.monsterName = monsterName;
  32. }
  33. public String getCrySound() {
  34. return crySound;
  35. }
  36. public void setCrySound(String crySound) {
  37. this.crySound = crySound;
  38. }
  39. public String getBookName() {
  40. return bookName;
  41. }
  42. public void setBookName(String bookName) {
  43. this.bookName = bookName;
  44. }
  45. public Double getResult() {
  46. return result;
  47. }
  48. public void setResult(Double result) {
  49. this.result = result;
  50. }
  51. //cry方法返回字符串
  52. public String cry(String sound){
  53. return "发出"+sound+"的叫声";
  54. }
  55. //read方法返回字符串
  56. public static String read(String bookName){
  57. return "正在看"+bookName;
  58. }
  59. @Override
  60. public String toString() {
  61. return "SpELBean{" +
  62. "name='" + name + '\'' +
  63. ", monster=" + monster +
  64. ", monsterName='" + monsterName + '\'' +
  65. ", crySound='" + crySound + '\'' +
  66. ", bookName='" + bookName + '\'' +
  67. ", result=" + result +
  68. '}';
  69. }
  70. }

配置beans03.xml:

  1. <!--配置一个Monster对象-->
  2. <bean class="com.li.bean.Monster" id="monster01">
  3. <property name="monsterId" value="100"/>
  4. <property name="name" value="蜈蚣精"/>
  5. <property name="skill" value="蜇人"/>
  6. </bean>
  7. <!--spring el 表达式使用-通过sp el给bean的属性赋值-->
  8. <bean class="com.li.bean.SpELBean" id="spELBean">
  9. <!--sp el 给字面量-->
  10. <property name="name" value="#{'一只猫猫'}"/>
  11. <!--sp el 引用其他 bean(该bean要存在)-->
  12. <property name="monster" value="#{monster01}"/>
  13. <!--sp el 引用其他 bean 的属性值-->
  14. <property name="monsterName" value="#{monster01.name}"/>
  15. <!--sp el 调用普通方法,将该方法的返回值赋给 bean对象的属性-->
  16. <property name="crySound" value="#{spELBean.cry('喵喵喵')}"/>
  17. <!--sp el 调用静态方法,将该方法的返回值赋给 bean对象的属性
  18. 注意:需要写上类全路径-->
  19. <property name="bookName" value="#{T(com.li.bean.SpELBean).read('红楼梦')}"/>
  20. <!--sp el 通过运算赋值-->
  21. <property name="result" value="#{89*1.0+33/3}"/>
  22. </bean>

测试类:

  1. //通过spring el 对属性赋值
  2. @Test
  3. public void setBeanBySpel() {
  4. ApplicationContext ioc = new ClassPathXmlApplicationContext("beans03.xml");
  5. SpELBean spELBean = ioc.getBean("spELBean", SpELBean.class);
  6. System.out.println(spELBean);
  7. }


day05-Spring管理Bean-IOC-03的更多相关文章

  1. (转)编码剖析Spring管理Bean的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52832434 在Spring的第一个案例中,我们已经知道了怎么将bean交给Spring容器进 ...

  2. 采用Spring管理Bean和依赖注入

    1. 实例化spring容器和从容器获取Bean对象 实例化Spring容器常用的两种方式: 方法一: 在类路径下寻找配置文件来实例化容器 [推荐使用] ApplicationContext ctx ...

  3. Spring管理bean的生命周期

    1: bean的创建:   如果我们默认的scope配置为Singleton的话, bean的创建实在Spring容器创建的时候创建: 如果scope的配置为Prototype的话,bena的创建是在 ...

  4. Spring、编码剖析Spring管理Bean的原理

    引入dom4j jar包 1.新建Person接口和PersonBean public interface PersonIService { public void helloSpring(); } ...

  5. Spring第三弹—–编码剖析Spring管理Bean的原理

    先附一下编写的Spring容器的执行结果: 代码如下: 模拟的Spring容器类:   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  6. Spring——管理Bean的生命周期

    我们可以自定义bean的初始化和销毁方法,这里所指的的初始化和bean的构造不同,初始化是在bean构造完成后,对bean内部的属性或一些逻辑进行初始化. 首先要弄清一些概念: 构造(对象创建) 单实 ...

  7. 编码剖析Spring管理bean的原理

    project目录 MyClassPathXMLApplicationContext读取xml,以及实例化bean. 因为是一开始实例化配置文件所有bean,所以需要构造器完成这些工作. packag ...

  8. Spring管理Bean的三种创建方式

    1.使用类构造器实例化  (90%以上都是使用这种) <bean id=“orderService" class="cn.itcast.OrderServiceBean&qu ...

  9. 简单模拟Spring管理Bean对象

    1: 首先我们要利用dom4j进行xml的解析,将所有的bean的配置读取出来. 2:利用java的反射机制进行对象的实例化. 3: 直接获得对象 package cn.Junit.test; imp ...

  10. spring 管理bean

    目录结构: Person.java package com.wss.entity; import com.wss.service.doHomeWork; public class Person { p ...

随机推荐

  1. 题解 P2080 增进感情

    \(\sf Link\) 爆搜最香了. 感觉有点像01背包(? 对于每件事,我们可以选择干或者不干,如果干就将好感值处理一下,当所有的事都搜完之后,记录最小值\(minn\) . 最终答案就是\(mi ...

  2. SpringBoot(三) - Ribbon客户端负载均衡,Zuul网关,Config配置中心

    1.Ribbon客户端负载均衡 1.1 依赖 1.2 配置信息 # feign默认加载了ribbon负载均衡,默认负载均衡机制是:轮询 # 负载均衡机制是添加在消费端(客户端)的,如果改为随机,指定服 ...

  3. ML-决策树

    信息增益 香农熵: 指混乱程度,越混乱,值越大 信息增益(information gain): 在划分数据集前后信息发生的变化称为信息增益(香农熵的差) 基尼不纯度也可度量集合的无序程度 香农熵的计算 ...

  4. web安全学习(sql注入1)

    web安全学习(sql注入1) 一.简介 sql语句就是数据库语句,而sql注入就是用户将自己构造的恶意sql语句提交,然后服务器执行提交的危险语句.sql注入可能造成信息泄露以及服务器被控制等危害. ...

  5. 【题解】CF45I TCMCF+++

    题面传送门 题目描述 有 \(n\) 个数 \(a_i\) 请你从中至少选出一个数,使它们的乘积最大 解决思路 对于正数,对答案一定有贡献(正数越乘越大),所以输入正数时直接输出即可. 对于负数,如果 ...

  6. 嵌入式-C语言基础:联合体和共用体的概念

    有时候同一块内存空间存放类型不同,不同类型的变量共享一块空间. 结构体和共用体的区别: (1)结构体元素有各自单独空间,共用体元素共享空间,空间大小由最大类型确定. (2)结构体元素互不影响共用体赋值 ...

  7. Go语言核心36讲11

    至今为止,我们讲过的集合类的高级数据类型都属于针对单一元素的容器. 它们或用连续存储,或用互存指针的方式收纳元素,这里的每个元素都代表了一个从属某一类型的独立值. 我们今天要讲的字典(map)却不同, ...

  8. Go语言核心36讲12

    作为Go语言最有特色的数据类型,通道(channel)完全可以与goroutine(也可称为go程)并驾齐驱,共同代表Go语言独有的并发编程模式和编程哲学. Don't communicate by ...

  9. python(牛客)试题解析2 - 中等

    导航 一.NC192 二叉树的后序遍历 二.NC117 合并二叉树 三.求长度最长的的连续子序列使他们的和等于sum 四.按顺序取出固定长度内容并合并两个数组为一个新数组 五.输出所有结果小于k的整数 ...

  10. 关于最新版本listen1 (2.1.6)的修改心得(添加下载功能)

    注:本文只作为技术交流 前言 再次感谢 listen1 的作者开发出如此强大的音乐播放器 项目地址 上一篇的文章没有解决跨域问题(命名不能正确命名), 上一篇文章 地址 这次解决了,并简单的美化了下载 ...