zoukankan      html  css  js  c++  java
  • IoC容器装配Bean(xml配置方式)(Bean的生命周期)

    1、Spring管理Bean,实例化Bean对象 三种方式

    第一种:使用类构造器实例化(默认无参数)

     1 package cn.itcast.spring.initbean;
     2 
     3 /**
     4  * 使用构造方法 实例化
     5  * 
     6  * @author seawind
     7  * 
     8  */
     9 public class Bean1 {
    10 
    11 }
    12 
    13     <!-- Bean 实例化第一种 方式 构造器 -->
    14     <bean id="bean1" class="cn.itcast.spring.initbean.Bean1"></bean>

    第二种:使用静态工厂方法实例化(简单工厂模式)

     1 package cn.itcast.spring.initbean;
     2 /**
     3  * 使用静态工厂方法进行Bean 实例化
     4  * 
     5  * @author seawind
     6  * 
     7  */
     8 public class Bean2 {
     9 
    10 }
    11 
    12 package cn.itcast.spring.initbean;
    13 // 工厂类
    14 public class Bean2Factory {
    15     public static Bean2 getBean2() {
    16         return new Bean2();
    17     }
    18 }
    19 
    20     <!-- Bean 实例化第二种 方式 静态工厂方法 -->
    21     <bean id="bean2" class="cn.itcast.spring.initbean.Bean2Factory" factory-method="getBean2" />

    第三种:使用实力工厂方法实例化(工厂方法模式)

     1 package cn.itcast.spring.initbean;
     2 /**
     3  * 通过实例 工厂方法进行构造
     4  * 
     5  * @author seawind
     6  * 
     7  */
     8 public class Bean3 {
     9 
    10 }
    11 
    12 package cn.itcast.spring.initbean;
    13 public class Bean3Factory {
    14     public Bean3 getBean3() {
    15         return new Bean3();
    16     }
    17 }
    18 
    19     <!-- Bean 实例化 第三种 方式  实例工厂方法 -->
    20     <bean id="bean3factory" class="cn.itcast.spring.initbean.Bean3Factory"></bean>
    21     <bean id="bean3" factory-bean="bean3factory" factory-method="getBean3"></bean>

    测试三种方式

     1 package cn.itcast.spring.initbean;
     2 
     3 import org.junit.Test;
     4 import org.springframework.context.ApplicationContext;
     5 import org.springframework.context.support.ClassPathXmlApplicationContext;
     6 
     7 /**
     8  * 实例化 Bean 三种方式
     9  * 
    10  * @author seawind
    11  * 
    12  */
    13 public class SpringTest {
    14     @Test
    15     // 实例工厂方法 实例化 Bean
    16     public void demo3() {
    17         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    18                 "applicationContext.xml");
    19         Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
    20         System.out.println(bean3);
    21     }
    22 
    23     @Test
    24     // 使用 静态工厂方法实例化Bean
    25     public void demo2() {
    26         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    27                 "applicationContext.xml");
    28         Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
    29         System.out.println(bean2);
    30     }
    31 
    32     @Test
    33     // 使用Bean 的构造方法 实例化Bean
    34     public void demo1() {
    35         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    36                 "applicationContext.xml");
    37         // Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
    38         // Spring3 集合 JDK5 泛型特性
    39         Bean1 bean1 = applicationContext.getBean("bean1", Bean1.class);
    40 
    41         System.out.println(bean1);
    42     }
    43 }

     2、Bean的id属性和name属性

    在使用Spring 配置Bean
        <bean id="helloService" class=".....HelloService" />
        <bean name="helloService" class="....HelloSerivce" />

    * 在配置Bean过程中 id 属性 和 name 属性 都行 ,都可以通过 applicationContext.getBean(id/name) 来获得一个Bean实例

    配置id 必须唯一,通常不含有特殊字符, 比如以/开始,以数字开始
    配置name 属性,不必须唯一, 可以含有特殊字符

    *  为什么要有name属性 ?
        比如 struts1 整合 spring 需要将 请求路径 配置到spring 中
            <bean id="/login" class="..... UserAction" />  ------ 在早期Spring版本 是报错的
            <bean name="/login" class="..... UserAction" /> ------ 以前整合都是这样写的

    3、 Bean的作用域
    在配置 <bean> 元素时, 通过 scope 属性 指定 Bean的作用域
        singleton : 代表Bean 在整个Spring 容器环境中 是单例的
        prototype : 多例 (原型模式) , 在一个Spring 容器中,每次使用Bean 都会返回一个新的实例
        request : 相当于 构造对象,保存request数据范围 (request.setAttribute())
        session : 相当于 构造对象,保存session数据范围 (session.setAttribute()) 以后再次使用,同一个Session无需构造  

    * 在实际开发中 只需要掌握 singleton 和 prototype 就可以了 ----- 默认值是 singleton   

    4、Bean 生命周期
    在配置 <bean> 通过 init-method destroy-method 定义Bean的初始化 和 销毁的方法

     1   applicationContext.xml: <bean id="product" class="cn.itcast.spring.lifecycle.Product" init-method="myinit" destroy-method="mydestroy"></bean>
     2     
     3     public class Product {
     4         public Product() {
     5             System.out.println("执行 Product的 构造 ...");
     6         }
     7 
     8         public void myinit() {
     9             System.out.println("Product对象初始化....");
    10         }
    11 
    12         public void mydestroy() {
    13             System.out.println("Product对象销毁....");
    14         }
    15     }
    16 
    17 @Test
    18     // 配置 init-method 和 destroy-method 执行 bean 的初始化和销毁 方法
    19     public void demo1() {
    20         ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    21                 "applicationContext.xml");
    22         Product product = (Product) applicationContext.getBean("product");
    23         System.out.println(product);
    24 
    25         // 如果销毁 Spring 手动 调用 close方法
    26         applicationContext.close();
    27     }

    有构造方法,为什么要有init ?

       java语言不建议在构造器 编写复杂处理逻辑,通常在构造器 只会成员变量赋值。初始化

    完整Bean的生命周期
        1) instantiate bean对象实例化
        2) populate properties 封装属性(setXxxx方法执行)
        3) 如果Bean实现BeanNameAware 执行 setBeanName(String beanName)
        4) 如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext

          * void setApplicationContext(ApplicationContext applicationContext)
        5) 如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
        6) 如果Bean实现InitializingBean 执行 afterPropertiesSet
        7) 调用<bean init-method="init"> 指定初始化方法 init
        8) 如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
        9) 执行业务处理
        10)如果Bean实现 DisposableBean 执行 destroy
        11)调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy

        3) 4) 知识点: 让Bean 了解Spring 容器
        5) Bean的后处理器 BeanPostProcessor ,该类成为Bean的后处理器
            * 后处理Bean 可以对 已经创建 Bean对象 进行代理增强

      1 package cn.itcast.spring.lifecycle;
      2 
      3 // 定义业务接口
      4  
      5 public interface CustomerService {
      6     public void addCustomer();
      7 }
      8 
      9 
     10 package cn.itcast.spring.lifecycle;
     11 
     12 import org.springframework.beans.BeansException;
     13 import org.springframework.beans.factory.BeanNameAware;
     14 import org.springframework.beans.factory.DisposableBean;
     15 import org.springframework.beans.factory.InitializingBean;
     16 import org.springframework.context.ApplicationContext;
     17 import org.springframework.context.ApplicationContextAware;
     18 
     19 // CustomerService 一个实现类 
     20 public class CustomerServiceImpl implements CustomerService, BeanNameAware,
     21         ApplicationContextAware, InitializingBean, DisposableBean {
     22     private String name;
     23 
     24     // 第一步
     25     public CustomerServiceImpl() {
     26         System.out.println("第一步 Bean的构造器执行....");
     27     }
     28 
     29     @Override
     30     public void addCustomer() {
     31         // 第九步 执行业务操作
     32         System.out.println("第九步 ,使用业务Bean 执行业务操作....");
     33         System.out.println("添加客户");
     34     }
     35 
     36     // 第二步
     37     public void setName(String name) {
     38         System.out.println("第二步  属性依赖注入....");
     39         this.name = name;
     40     }
     41 
     42     @Override
     43     // 第三步,如果 Bean 实现 BeanNameAware, Spring 就会将 <bean> 配置 id 属性 、name 属性 注入
     44     public void setBeanName(String beanName) {
     45         System.out.println("第三步 获得当前Bean在Spring 注册 Bean 名字 :" + beanName);
     46     }
     47 
     48     @Override
     49     // 第四步 如果 Bean 实现 ApplicationContextAware, Spring 就会将Spring 应用上下文 注入给 Bean
     50     public void setApplicationContext(ApplicationContext applicationContext)
     51             throws BeansException {
     52         System.out.println("第四步 获得当前 Spring上下文 :" + applicationContext);
     53         // 通过该对象 操作其它Bean
     54     }
     55 
     56     @Override
     57     // 第六步
     58     public void afterPropertiesSet() throws Exception {
     59         System.out.println("第六步 属性封装完成 ....");
     60     }
     61 
     62     // 第七步 通过配置文件,指定初始化方法
     63     public void myinit() {
     64         System.out.println("第七步  自定义初始化方法...");
     65     }
     66 
     67     @Override
     68     // 第十步 释放资源
     69     public void destroy() throws Exception {
     70         System.out.println("第十步, 不需要配置 调用释放资源方法");
     71     }
     72 
     73     // 第十一步
     74     public void mydestroy() {
     75         System.out.println("第十一步  自定义 释放资源方法");
     76     }
     77 
     78 }
     79 
     80 package cn.itcast.spring.lifecycle;
     81 
     82 import java.lang.reflect.InvocationHandler;
     83 import java.lang.reflect.Method;
     84 import java.lang.reflect.Proxy;
     85 
     86 import org.springframework.beans.BeansException;
     87 import org.springframework.beans.factory.config.BeanPostProcessor;
     88 
     89 // 自定义 一个 Bean的 后处理器
     90 
     91 public class MyBeanPostProcessor implements BeanPostProcessor {
     92 
     93     @Override
     94     // 提供两个方法,用户通过实现 两个方法,对原有Bean 进行增强
     95     // 第八步
     96     /**
     97      * beanName 就是 配置文件 <bean> id 属性
     98      * bean 增强前对象
     99      */
    100     public Object postProcessAfterInitialization(final Object bean,
    101             String beanName) throws BeansException {
    102         System.out.println("第八步 BeanPostProcessor 后处理Bean 初始化完成后增强....");
    103         // 通过beanName 判断要对哪个Bean 进行代理增强
    104         if (beanName.equals("customerService")) {
    105             // 增强
    106             return Proxy.newProxyInstance(bean.getClass().getClassLoader(),
    107                     bean.getClass().getInterfaces(), new InvocationHandler() {
    108                         @Override
    109                         public Object invoke(Object proxy, Method method,
    110                                 Object[] args) throws Throwable {
    111                             if (method.getName().equals("addCustomer")) { // 增强
    112                                 System.out
    113                                         .println("增强addCustomer=======================================");
    114                             }
    115 
    116                             // 不增强
    117                             return method.invoke(bean, args);
    118                         }
    119                     });
    120         }
    121         return bean;
    122     }
    123 
    124     @Override
    125     // 第五步
    126     public Object postProcessBeforeInitialization(Object bean, String beanName)
    127             throws BeansException {
    128         System.out.println("第五步BeanPostProcessor 后处理Bean 初始化完成前增强... ");
    129         return bean;
    130     }
    131 
    132 }
    133 
    134 @Test
    135     // 通过CustomerService 来理解Bean 的生命周期
    136     public void demo2() {
    137         ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    138                 "applicationContext.xml");
    139         CustomerService customerService = (CustomerService) applicationContext
    140                 .getBean("customerService");
    141         customerService.addCustomer();
    142 
    143         applicationContext.close();
    144     }
    145 
    146 
    147 <!-- 可以配置Bean 初始化和销毁 调用方法 -->
    149     <bean id="customerService" class="cn.itcast.spring.lifecycle.CustomerServiceImpl" init-method="myinit" destroy-method="mydestroy">
    150         <property name="name" value="张三"></property>
    151     </bean>
    152     
    153     <!-- 配置后处理Bean ,不需要为Bean 指定id ,会对所有Bean 产生作用 -->
    154      <bean class="cn.itcast.spring.lifecycle.MyBeanPostProcessor"></bean>

    结果:

     

  • 相关阅读:
    ValidateInput(false)与this.ValidateRequest = false无效的解决方案
    WPF ListView CellTemplate Border设置ListView单元格的边框
    MFC4简单的窗口重绘(非部分重绘)
    针对每个用户的作业(针对用户的定期事件)
    用JQUERY做大表单(多表单域)AJAX提交
    MFC2消息处理
    asp.net mvc实战学习笔记(1)
    NHibernate基础拾遗
    FLEX/FLASH冒泡事件与非冒泡事件
    MFC1创建窗体
  • 原文地址:https://www.cnblogs.com/kingxiaozi/p/3387740.html
Copyright © 2011-2022 走看看