zoukankan      html  css  js  c++  java
  • Spring IOC/DI/注解

    一、定义Spring 是一个开源的控制反转(Inversion of Control,IoC/DI)和面向切面(AOP)的容器框架,它的主要目的是简化企业开发

    二、实例化Spring容器:

    方法一:在类路径下寻找配置文件来实例化容器

    1 ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{“beans.xml”});

    方法二:在文件系统路径下寻找配置文件来实例化容器

    1 ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:""beans.xml”});

    注:文件可指定多个

    可建立单元测试来测试Spring容器的初始化

    三、编写Spring 配置文件时,不能出现帮助信息的解决办法添加schema文件

    由于Springschema文件位于网络上,如果机器不能连接到网络,那么在写配置文件的时候就无法出现提示信息,解决办法有两种:

    1. 让机器上网,Eclipse会自动从网络上下载schema文件并缓存在硬盘上

    2手动添加schema文件,方法如下:

    windows->preferences->myeclipse->files and editors->xml->xmlcatalog

    a. 我们可以选择将schema文件放到User Specified Entries然后点击‘add’,在出现的窗口中的Key Type中选择URL ‘Location’中选择‘File System’,然后在Spring解压目录的dist/resources目录中选择spring-beans-2.5.xsd

    b. 回到设置窗口时候不要急于关闭窗口,应把窗口中的Key Type改为schema location

    c. key改为:

    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

    四、Spring 配置文件一个小插曲

    <bean id=”” name=””></bean>,在这里,id name都是为这个bean取的名字,其实这两者意思相同,只是如果选择使用的是id,那么id命名则不能有特殊字符,如果使用的是name则可以使用特殊字符作为name。如

    1 <bean id=”beanId” /> && <bean name=”bean-name”/>

    五、Spring容器如何管理bean

    首先读取beans.xml里的bean配置所有的idclass的值,作为String形式保存至对应一个Bean,形成bean列表

    利用反射机制,将bean列表遍历,生成对象,如下:

      1 package junit.test;
      2 
      3 import java.net.URL;
      4 
      5 import java.util.ArrayList;
      6 
      7 import java.util.HashMap;
      8 
      9 import java.util.HashSet;
     10 
     11 import java.util.List;
     12 
     13 import java.util.Map;
     14 
     15 import org.dom4j.Document;
     16 
     17 import org.dom4j.Element;
     18 
     19 import org.dom4j.XPath;
     20 
     21 import org.dom4j.io.SAXReader;
     22 
     23 /**
     24 
     25  *传智传客版容器
     26 
     27  *
     28 
     29  */
     30 
     31 publicclass ItcastClassPathXMLApplicationContext {
     32 
     33     private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
     34 
     35     private Map<String, Object> sigletons = new HashMap<String, Object>();
     36 
     37    
     38 
     39     public ItcastClassPathXMLApplicationContext(String filename){
     40 
     41         this.readXML(filename);
     42 
     43         this.instanceBeans();
     44 
     45     }
     46 
     47     /**
     48 
     49      *完成bean的实例化
     50 
     51      */
     52 
     53     privatevoid instanceBeans() {
     54 
     55         for(BeanDefinition beanDefinition : beanDefines){
     56 
     57             try {
     58 
     59                 if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
     60 
     61                     sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
     62 
     63             } catch (Exception e) {
     64 
     65                 e.printStackTrace();
     66 
     67             }
     68 
     69         }
     70 
     71     }
     72 
     73     /**
     74 
     75      *读取xml配置文件
     76 
     77      *@paramfilename
     78 
     79      */
     80 
     81     privatevoid readXML(String filename) {
     82 
     83         SAXReader saxReader = new SAXReader();
     84 
     85         Document document = null;
     86 
     87         try {
     88 
     89             URL xmlpath = this.getClass().getClassLoader().getResource(filename);
     90 
     91             document = saxReader.read(xmlpath);
     92 
     93             Map<String, String> nsMap = new HashMap<String, String>();
     94 
     95             nsMap.put("ns", "http://www.springframework.org/schema/beans");// 加入命名空间
     96 
     97             XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
     98 
     99             xsub.setNamespaceURIs(nsMap);// 设置命名空间
    100 
    101             List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点
    102 
    103             for (Element element : beans) {
    104 
    105                 String id = element.attributeValue("id");// 获取id属性值
    106 
    107                 String clazz = element.attributeValue("class"); // 获取class属性值
    108 
    109                 BeanDefinition beanDefine = new BeanDefinition(id, clazz);
    110 
    111                 beanDefines.add(beanDefine);
    112 
    113             }
    114 
    115         } catch (Exception e) {
    116 
    117             e.printStackTrace();
    118 
    119         }
    120 
    121     }
    122 
    123     /**
    124 
    125      *获取bean实例
    126 
    127      *@parambeanName
    128 
    129      *@return
    130 
    131      */
    132 
    133     public Object getBean(String beanName){
    134 
    135         returnthis.sigletons.get(beanName);
    136 
    137     }
    138 
    139 }

    六、Spring的三种实例化Bean方式

    1使用构造器实例化

    1 <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>

    这种就是利用默认的构造器进行的实例化

    2. 静态工厂方法实例化

     

    1 <bean id="personService2" class="cn.itcast.service.impl.PersonServiceBeanFactory" factory-method="createPersonServiceBean"/>

     

    3. 使用实例工厂方法实例化

     

    1 <bean id="personServiceFactory" class="cn.itcast.service.impl.PersonServiceBeanFactory"/>
    2 
    3 <bean id="personService3" factory-bean="personServiceFactory" factory-method="createPersonServiceBean2"/>

     

    七、bean的作用域-属性scope

    singleton:(默认)在每个Spring IOC容器中一个bean定义只有一个对象实例,默认情况下会在容器启动时初始化bean。但我们可以指定bean节点lazy-init=”true” 则表示不需要在容器初始化时候对bean进行初始化,只有在第一次getBean时候进行初始化,如果需要所有的bean都应用延迟初始化,可以在根节点<beans>设置default-lazy-init=”true”(不推荐,不利于观察bean初始化情况)

    prototype:每次从容器中获取的bean都是新的对象

    request

    session

    global session

    七、Spring管理的bean的生命周期

    默认情况下容器初始化的时候对bean进行实例化

    如果scopeprototype时,在调用getBean方法时候对bean进行实例化

    如果lazy-inittrue时,容器初始化时候不会对bean进行实例化

    综上所述,Spring管理的bean初始化点根据设定的条件不同而不同

    init-method:在bean被实例化的后即会执行的方法

    destroy-method:在bean被销毁的时候执行的方法(如果没有手动的销毁该bean,则只有在容器关闭的时候才会销毁)

    正常的关闭Spring容器

    1 AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    2 
    3 ctx.close();

    八、控制反转IoC 定义:

     1 Public class PersonServiceBean {
     2 
     3 Private PersonDao personDao = new PersonDaoBean();
     4 
     5 Public void save (Person person) {
     6 
     7 personDao.save(person);
     8 
     9 }
    10 
    11 }

    PersonDaoBean是在应用内部创建和维护的,所谓的控制反转就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,控制权的转移就是所谓的反转。

    九、依赖注入(Dependency Injection)的定义:

    当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:

     

     1 public class PersonServiceBean{
     2 
     3 private PersonDao personDao;
     4 
     5 //通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入
     6 
     7 public PersonServiceBean(PersonDao personDao) {
     8 
     9 this.personDao = personDao;
    10 
    11 }
    12 
    13 Public void save(Person person) {
    14 
    15 personDao.save(person);
    16 
    17 }
    18 
    19 }

     

    所谓的依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中

    十、依赖注入:

    1.使用构造器注入

     1     private PersonDao personDao;
     2 
     3     private String name;   
     4 
     5     public PersonServiceBean(PersonDao personDao, String name) 
     6    {
     7 
     8         this.personDao = personDao;
     9 
    10         this.name = name;
    11 
    12     }

    beans.xml配置:

    1 <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
    2 
    3 <constructor-arg index="0" type="cn.itcast.dao.PersonDao" ref=""></constructor-arg>
    4 
    5     <constructor-arg index="1" type="paramValue"></constructor-arg>
    6 
    7 </bean>

    2.使用setter方法注入

    ref形式注入:

    1     <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
    2 
    3         <property name="personDao" ref="personDaoBean" />
    4 
    5     </bean>

    可以采用内部bean方式进行注入,不同过ref方式的是,这种内部bean注入对于bean的重用性效果不好:

     

    1     <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
    2 
    3         <property name="personDao">
    4 
    5             <bean class="cn.itcast.dao.impl.PersonDaoBean" />
    6 
    7         </property>
    8 
    9     </bean>

     

    bean基本类型的注入:

     1     <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
     2 
     3         <property name="personDao">
     4 
     5             <bean class="cn.itcast.dao.impl.PersonDaoBean" />
     6 
     7         </property>
     8 
     9         <property name="name" value="itcast" />
    10 
    11         <property name="id" value="100" />
    12 
    13     </bean>

    集合类的注入:

     1 <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" >
     2 
     3         <property name="sets">
     4 
     5             <set>
     6 
     7                 <value>第一个</value>
     8 
     9                 <value>第二个</value>
    10 
    11                 <value>第三个</value>
    12 
    13             </set>
    14 
    15         </property>
    16 
    17         <property name="lists">
    18 
    19             <list>
    20 
    21                 <value>第一个list元素</value>
    22 
    23                 <value>第二个list元素</value>
    24 
    25                 <value>第三个list元素</value>
    26 
    27             </list>
    28 
    29         </property>
    30 
    31         <property name="properties">
    32 
    33             <props>
    34 
    35                 <prop key="key1">value1</prop>
    36 
    37                 <prop key="key2">value2</prop>
    38 
    39                 <prop key="key3">value3</prop>
    40 
    41             </props>
    42 
    43         </property>
    44 
    45         <property name="maps">
    46 
    47             <map>
    48 
    49                 <entry key="key-1" value="value-1" />
    50 
    51                 <entry key="key-2" value="value-2" />
    52 
    53                 <entry key="key-3" value="value-3" />
    54 
    55             </map>
    56 
    57         </property>
    58 
    59 </bean>

    3.使用Field注入(用于注解方式)

    注入依赖对象,可以采用手工装配或者自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终装配的结果

    1.     手工装配依赖对象

    a)       xml配置文件中,通过在bean节点下配置

    b)       java代码中使用@Autowired@Resource注解方式进行装配。但我们需要在xml配置以下信息

     

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 
     3 <beans xmlns="http://www.springframework.org/schema/beans"
     4 
     5        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     6 
     7        xmlns:context="http://www.springframework.org/schema/context"      
     8 
     9        xsi:schemaLocation="http://www.springframework.org/schema/beans         
    10 
    11 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    12 
    13 http://www.springframework.org/schema/context
    14 
    15 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    16 
    17 <!-- 相当于启用解析注解的处理器 -->
    18 
    19 <context:annotation-config/>
    20 
    21 </beans>

     

    这个配置隐式注册了多个注释进行解析处理的处理器:

    注解本身不做任何事情,只是利用这些处理器来达到配置一样的效果

    AutowiredAnnotationBeanPostProcessor,

    CommonAnnotationBeanPostProcesor,

    PersistenceAnnotationBeanPostProcessor,

    RquiredAnnotationBeanPostProcessor

    注:@Resource注解在spring安装目录的lib/j2ee/common-annotations.jar

    jar文件:

    dist/spring.jar

    lib/Jakarta-commons/commons-logging.jar

    lib/aspectjaspectjweaver.jaraspectjrt.jar//aop

    lib/cglib/cglib-nodep-2.1_3.jar

    lib/j2ee/common-annotations.jar

    java代码中使用@Autowired@Resource注解方式进行装配,这两个注解的区别是:

    @Autowired默认按类型装配,@Resource默认按照名称装配,当找不到与名称匹配的bean才会匹配的bean才会按类型装配

    @Autowired

    private PersonDao personDao;    //用于字段上

    @Autowired

    public void setOrderDao(OrderDao orderDao) {    //用于属性的setter方法上

        this.orderDao = orderDao;

    }

    @Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false(默认是true),如果我们想按名称装配,可以结合@Qualifier注解一起使用,如下:

    @Autowired @Qualifier(“personDaoBean”)

    private PersonDao personDao;

    如上面的注解,则@Autowired本身是按照类型装配,现在将会按名称装配

    @Resource注解和@Actowired一样,也可以标注在字段或者属性的setter方法上,但他默认按照名称装配。名称可以通过@Resourcename属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

    @Resource(name=”personDaoBean”)

    private PersonDao personDao;

    注意:如果没有指定name属性,并且暗号默认的名称仍然找不到依赖对象时,“Resource注解会回退到按类型装配,但一旦指定了name属性,就只能按名称装配了

    2.自动装配依赖对象

    对于自动装配,作为了解

    byType:按类型装配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。如果发现多个,那么将会抛出异常。如果没有找到,即属性值为null

    byName:按名称装配,可以根据属性的名称在容器中寻找跟该属性名相同的bean,如果没有找到,即属性值为null

    constructorbyType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常

    autodetect:通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式

    十一、依赖注入的原理

    Spring容器管理bean原理的实例中进行改造,该例子涉及到两个实体类:BeanDefinition{id,class}PropertyDefinition{name,ref}

      1 package junit.test;
      2 
      3 import java.beans.IntrospectionException;
      4 
      5 import java.beans.Introspector;
      6 
      7 import java.beans.PropertyDescriptor;
      8 
      9 import java.lang.reflect.Method;
     10 
     11 import java.net.URL;
     12 
     13 import java.util.ArrayList;
     14 
     15 import java.util.HashMap;
     16 
     17 import java.util.List;
     18 
     19 import java.util.Map;
     20 
     21 import org.dom4j.Document;
     22 
     23 import org.dom4j.Element;
     24 
     25 import org.dom4j.XPath;
     26 
     27 import org.dom4j.io.SAXReader;
     28 
     29 /**
     30 
     31  *传智传客版容器
     32 
     33  *
     34 
     35  */
     36 
     37 publicclass ItcastClassPathXMLApplicationContext {
     38 
     39     private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
     40 
     41     private Map<String, Object> sigletons = new HashMap<String, Object>();
     42 
     43    
     44 
     45     public ItcastClassPathXMLApplicationContext(String filename){
     46 
     47         this.readXML(filename);
     48 
     49         this.instanceBeans();
     50 
     51         this.injectObject();
     52 
     53     }
     54 
     55     /**
     56 
     57      *为bean对象的属性注入值
     58 
     59      */
     60 
     61     privatevoid injectObject() {
     62 
     63         for(BeanDefinition beanDefinition : beanDefines){
     64 
     65             Object bean = sigletons.get(beanDefinition.getId());
     66 
     67             if(bean!=null){
     68 
     69                 try {
     70 
     71                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
     72 
     73                     for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
     74 
     75                         for(PropertyDescriptor properdesc : ps){
     76 
     77                             if(propertyDefinition.getName().equals(properdesc.getName())){
     78 
     79                                 Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
     80 
     81                                 if(setter!=null){
     82 
     83                                     Object value = sigletons.get(propertyDefinition.getRef());
     84 
     85                                     setter.setAccessible(true);
     86 
     87                                     setter.invoke(bean, value);//把引用对象注入到属性
     88 
     89                                 }
     90 
     91                                 break;
     92 
     93                             }
     94 
     95                         }
     96 
     97                     }
     98 
     99                 } catch (Exception e) {
    100 
    101                 }
    102 
    103             }
    104 
    105         }
    106 
    107     }
    108 
    109     /**
    110 
    111      *完成bean的实例化
    112 
    113      */
    114 
    115     privatevoid instanceBeans() {
    116 
    117         for(BeanDefinition beanDefinition : beanDefines){
    118 
    119             try {
    120 
    121                 if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
    122 
    123                     sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
    124 
    125             } catch (Exception e) {
    126 
    127                 e.printStackTrace();
    128 
    129             }
    130 
    131         }
    132 
    133        
    134 
    135     }
    136 
    137     /**
    138 
    139      *读取xml配置文件
    140 
    141      *@paramfilename
    142 
    143      */
    144 
    145     privatevoid readXML(String filename) {
    146 
    147            SAXReader saxReader = new SAXReader();  
    148 
    149             Document document=null;  
    150 
    151             try{
    152 
    153              URL xmlpath = this.getClass().getClassLoader().getResource(filename);
    154 
    155              document = saxReader.read(xmlpath);
    156 
    157              Map<String,String> nsMap = new HashMap<String,String>();
    158 
    159              nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间
    160 
    161              XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
    162 
    163              xsub.setNamespaceURIs(nsMap);//设置命名空间
    164 
    165              List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点
    166 
    167              for(Element element: beans){
    168 
    169                 String id = element.attributeValue("id");//获取id属性值
    170 
    171                 String clazz = element.attributeValue("class"); //获取class属性值       
    172 
    173                 BeanDefinition beanDefine = new BeanDefinition(id, clazz);
    174 
    175                 XPath propertysub = element.createXPath("ns:property");
    176 
    177                 propertysub.setNamespaceURIs(nsMap);//设置命名空间
    178 
    179                 List<Element> propertys = propertysub.selectNodes(element);
    180 
    181                 for(Element property : propertys){                 
    182 
    183                  String propertyName = property.attributeValue("name");
    184 
    185                  String propertyref = property.attributeValue("ref");
    186 
    187                  PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref);
    188 
    189                  beanDefine.getPropertys().add(propertyDefinition);
    190 
    191                 }
    192 
    193                 beanDefines.add(beanDefine);
    194 
    195              }
    196 
    197             }catch(Exception e){  
    198 
    199                 e.printStackTrace();
    200 
    201             }
    202 
    203     }
    204 
    205     /**
    206 
    207      *获取bean实例
    208 
    209      *@parambeanName
    210 
    211      *@return
    212 
    213      */
    214 
    215     public Object getBean(String beanName){
    216 
    217         returnthis.sigletons.get(beanName);
    218 
    219     }
    220 
    221 }

    Spring 开发的好处

    a)       降低组件之间的耦合度,实现软件各层之间的解耦

     Controller -- Service -- Dao

    b) 可是使用容器提供的众多服务

    可使用容器提供的众多服务:事务管理服务(事务传播,无需手工控制事务)、JMS服务、Spring core核心服务、持久化服务、其他……

    c) 容器提供单例模式支持,开发人员不再需要自己编写实现代码

    d) 容器提供了AOP技术,利用它狠容易实现如权限拦截,运行期监控等功能

    e) 容器提供了众多的辅助类,使用这些类,能够加快应用的开发,如:Jdbc TemplateHibernate Template

    f) Spring 对于主流的应用框架提供了集成支持,如:集成HibernateJPAStruts等,这样更便于应用的开发

    十三、 Spring DI配置文件减肥(Spring2.0 –Spring2.5的升级)

    1@Resource注解

    2.注解使Spring 自动扫描和管理bean

    扫描路径:<context:component-scan base-package=”cn.itcast” />,将会扫描该包下包括其子包的类

    @Component:泛指组件、当组件不好归类的时候,我们可以使用这个注解进行标注

    @Service:用于标注业务层组件

    @Controller:用于标注控制层组件(如struts中的action

    @Repository:用于标注数据访问组件,即DAO组件

    此时bean默认的名称为类全名首写字母小写,也可指定bean名称,如

    @Service(“personService”)

    下面有几个例子:

    service组件的注解

     

     1 package cn.itcast.service.impl;
     2 
     3 import javax.annotation.PostConstruct;
     4 
     5 import javax.annotation.PreDestroy;
     6 
     7 import org.springframework.stereotype.Service;
     8 
     9 import cn.itcast.dao.PersonDao;
    10 
    11 import cn.itcast.service.PersonService;
    12 
    13 @Service("personService") @Scope("prototype")    //这样可以修改bean作用域
    14 
    15 public class PersonServiceBean implements PersonService {
    16 
    17     //@Autowired(required=false) @Qualifier("personDaoxxxx")
    18 
    19     private PersonDao personDao;
    20 
    21    
    22 
    23     //初始化bean时会执行该方法的注解(ejb3中同样应用)
    24 
    25     @PostConstruct
    26 
    27     public void init(){
    28 
    29         System.out.println("初始化");
    30 
    31     }
    32 
    33    
    34 
    35     //销毁bean之前会执行该方法的注解(ejb3中同样应用)
    36 
    37     @PreDestroy
    38 
    39     public void destory(){
    40 
    41         System.out.println("开闭资源");
    42 
    43     }
    44 
    45    
    46 
    47     public void setPersonDao(PersonDao personDao) {
    48 
    49         this.personDao = personDao;
    50 
    51     }
    52 
    53     public void save(){
    54 
    55         personDao.add();
    56 
    57     }
    58 
    59 }

     

    dao组件的注解

     

     1 package cn.itcast.dao.impl;
     2 
     3 import org.springframework.stereotype.Repository;
     4 
     5 import cn.itcast.dao.PersonDao;
     6 
     7 @Repository
     8 
     9 public class PersonDaoBean implements PersonDao {
    10 
    11     public void add(){
    12 
    13         System.out.println("执行PersonDaoBean中的add()方法");
    14 
    15     }
    16 
    17 }

     

    Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法

    使用时只需要在方法前标注 @PostConstruct @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring容器执行了,我们知道,不管是通过实现 InitializingBean/DisposableBean 接口,还是通过 <bean> 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct @PreDestroy 注释的方法都会在初始化 / 销毁时被执行。

     

     

     

     

     

     

     

  • 相关阅读:
    最高效的无限级菜单生成方法
    MySQL性能优化的最佳20+条经验(转)
    Web应用中的轻量级消息队列
    Delphi Setlength 内存释放总结
    Delphi 的TSpeedButton按下和弹起效果
    Delphi存取图像完整解决方案
    delphi 开机自动运行代码
    有关时间限制使用和软件注册的设计(delphi)
    Linux环境thinkphp配置以及数据源驱动改动
    Dalvik和ART简单介绍
  • 原文地址:https://www.cnblogs.com/smart9595/p/3714607.html
Copyright © 2011-2022 走看看