spring注解之@PostConstruct在項目啟動時執行指定方法


一、注解解釋

Spring的@PostConstruct注解在方法上,表示此方法是在Spring實例化該Bean之后馬上執行此方法,之后才會去實例化其他Bean,並且一個Bean中@PostConstruct注解的方法可以有多個。

二、示例代碼

1. spring配置文件

<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="  
http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-3.0.xsd  
">  
  
    <!-- 引入屬性文件 -->  
    <context:property-placeholder location="classpath:config.properties" />  
  
    <!-- 自動掃描dao和service包(自動注入) -->  
    <context:component-scan base-package="com.wbf.bean" />  
  
</beans>  

 2. Bean1.java

 1 package com.wbf.bean;  
 2   
 3 import javax.annotation.PostConstruct;  
 4   
 5 import org.apache.log4j.Logger;  
 6 import org.springframework.stereotype.Service;  
 7   
 8 @Service("bean1")  
 9 public class Bean1 {  
10       
11     private static final Logger log = Logger.getLogger(Bean1.class);  
12       
13     public Bean1() {  
14         log.info(System.currentTimeMillis() + ": Bean1 Constructor");  
15     }  
16       
17     @PostConstruct  
18     public void test() {  
19         log.info(System.currentTimeMillis() + ": bean1-->test()");  
20         Bean2.uniqueInstance().test();  
21           
22     }  
23       
24     @PostConstruct  
25     public void print() {  
26         log.info(System.currentTimeMillis() + ": bean1-->print()");  
27     }  
28 }  

3. Bean2.java

package com.wbf.bean;  
  
import org.apache.log4j.Logger;  
  
public class Bean2 {  
      
    private static final Logger log = Logger.getLogger(Bean2.class);  
      
    private static Bean2 instance = uniqueInstance();  
      
    public static Bean2 uniqueInstance() {  
        if (instance == null)  
            instance = new Bean2();  
          
        return instance;  
    }  
      
    public Bean2() {  
        log.info(System.currentTimeMillis() + ": Bean2 Construtor");  
    }  
    
    public void test() {  
        log.info(System.currentTimeMillis() + ": bean2-->test()");  
    }  
}  

4.  Bean3.java

 1 package com.wbf.bean;  
 2   
 3 import org.apache.log4j.Logger;  
 4 import org.springframework.stereotype.Service;  
 5   
 6 @Service("bean3")  
 7 public class Bean3 {  
 8       
 9     private static final Logger log = Logger.getLogger(Bean3.class);  
10       
11     public Bean3() {  
12         log.info(System.currentTimeMillis() + ": Bean3 Construtor");  
13     }  
14       
15 }  

5. SpringTest.java

 1 package com.wbf.bean;  
 2   
 3 import org.junit.Test;  
 4 import org.springframework.context.ApplicationContext;  
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;  
 6   
 7 public class SpringTest {  
 8       
 9     @Test  
10     public void test() {  
11         //加載/解析spring.xml, 得到BeanFactory, 實例化所有IOC容器中的Bean  
12         //在實例化每一個Bean之后,如果當前Bean包含@PostConstruct注解的方法則會馬上執行該方法,之后才會去實例化其他的Bean  
13         //每一個Bean中可以有多個包含@PostConstruct注解的方法  
14         ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"classpath:spring.xml"});  
15     }  
16       
17 }  

 運行結果:

[org.springframework.context.support.ClassPathXmlApplicationContext]Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b0f2b2: startup date [Thu Jun 11 11:51:17 CST 2015]; root of context hierarchy  
[org.springframework.beans.factory.xml.XmlBeanDefinitionReader]Loading XML bean definitions from class path resource [spring.xml]  
[org.springframework.beans.factory.config.PropertyPlaceholderConfigurer]Loading properties file from class path resource [config.properties]  
[org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor]JSR-330 'javax.inject.Inject' annotation found and supported for autowiring  
[org.springframework.beans.factory.support.DefaultListableBeanFactory]Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1b8dc93: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,bean1,bean3,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy  
[com.wbf.bean.Bean1]1433994678340: Bean1 Constructor  
[com.wbf.bean.Bean1]1433994678347: bean1-->print()  
[com.wbf.bean.Bean1]1433994678347: bean1-->test()  
[com.wbf.bean.Bean2]1433994678348: Bean2 Construtor  
[com.wbf.bean.Bean3]1433994678348: Bean3 Construtor  

從運行結果可以看出Spring在實例化Bean1之后馬上執行了它的@PostConstruct注解的方法print()和test(),之后才去實例化Bean3。其中Bean2沒有被Spring IOC容器管理。

三、補充說明

1.@PostConstruct說明

     被@PostConstruct修飾的方法會在服務器加載Servlet(bean)的時候運行,並且只會被服務器調用一次,類似於Serclet的inti()方法。被@PostConstruct修飾的方法會在構造函數之后,init()方法之前運行。

2.@PreDestroy說明

     被@PreDestroy修飾的方法會在服務器卸載Servlet(bean)的時候運行,並且只會被服務器調用一次,類似於Servlet的destroy()方法。被@PreDestroy修飾的方法會在destroy()方法之后運行,在Servlet被徹底卸載之前

 

另外,spring中Constructor、@Autowired、@PostConstruct的順序

其實從依賴注入的字面意思就可以知道,要將對象p注入到對象a,那么首先就必須得生成對象a和對象p,才能執行注入。所以,如果一個類A中有個成員變量p被@Autowried注解,那么@Autowired注入是發生在A的構造方法執行完之后的。

如果想在生成對象時完成某些初始化操作,而偏偏這些初始化操作又依賴於依賴注入,那么久無法在構造函數中實現。為此,可以使用@PostConstruct注解一個方法來完成初始化,@PostConstruct注解的方法將會在依賴注入完成后被自動調用。

Constructor >> @Autowired >> @PostConstruct

舉個例子:

 1    public Class AAA{
 2         @Autowired
 3         private BBB b;
 4         
 5         public AAA() {
 6              System.out.println("此時b還未被注入: b = " + b);
 7         }
 8         @PostConstruct
 9         private void init () {
10              System.out.println("@PostConstruct將在依賴注入完成后被自動調用: b = " + b);
11         }
12     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM