1. 程式人生 > >spring4.1.8擴充套件實戰之二:Aware介面揭祕

spring4.1.8擴充套件實戰之二:Aware介面揭祕

接下來通過分析spring原始碼,我們來看看典型的Aware子類有哪些,使用場景是什麼?

在spring容器初始化過程中,會執行AbstractApplicationContext類的prepareBeanFactory方法,這裡面會建立一個bean後置處理器ApplicationContextAwareProcessor,如下圖紅框所示:
這裡寫圖片描述

在bean被初始化之前,所有的bean後置處理器的postProcessBeforeInitialization方法都會被執行,如下圖紅框所示:
這裡寫圖片描述

由以上兩步可以確定:對於每個bean後置處理器來說,它的postProcessBeforeInitialization方法會在每個bean的初始化之前被呼叫一次;

來看看ApplicationContextAwareProcessor類的postProcessBeforeInitialization方法,按照前面的分析,該方法在每個bean被初始化之前都會被執行,如下圖紅框所示,invokeAwareInterfaces方法會被呼叫,這是我們要關注的重點:
這裡寫圖片描述

展開invokeAwareInterfaces方法看看:

private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver( new EmbeddedValueResolver(this.applicationContext.getBeanFactory())); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }

從上述程式碼可以看出,如果當前的bean實現了某個介面,那麼它的某個對應的方法就會被呼叫,例如我們建立了一個bean實現了ApplicationContextAware介面,那麼這個bean的setApplicationContext方法就會被呼叫,入參是applicationContext成員變數,這樣我們的bean就能得到applicationContext物件了;

以上就是Aware的介面使用原理:業務按需要實現特定的Aware介面,spring容器會主動找到該bean,然後呼叫特定的方法,將特定的引數傳遞給bean; BeanNameAware介面的呼叫場景

BeanNameAware也是Aware的子介面,不過它的呼叫場景和前面分析的幾個Aware子介面不同,並未出現在ApplicationContextAwareProcessor類的invokeAwareInterfaces方法中,我們來看看它是如何被呼叫的;

如下圖所示,紅框中就是BeanNameAware介面被呼叫的地方,而綠框中的applyBeanPostProcessorsBeforeInitialization方法就是前面我們分析的那些Aware子介面被呼叫的位置:
這裡寫圖片描述

方法invokeAwareMethods如下所示,和前面的討論一樣,特定型別的bean,其特定的方法被呼叫,傳入特定的入參:

private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }

實戰,通過Aware介面得到想要的物件

瞭解Aware介面在spring環境中的用法之後,我們可以通過實戰來驗證前面所學了,本次實戰我們建立兩個類,分別實現ApplicationContextAware和BeanNameAware這兩個介面,看宣告的方法是否能被呼叫,並驗證傳入的物件是否有效(文章結尾處提供本次實戰的工程原始碼下載);

  1. 基於maven新建一個SpringBoot的web工程customizeaware;
  2. 新建工具類Utils,提供靜態方法printTrack用於列印當前執行緒堆疊資訊:

package com.bolingcavalry.customizeaware.util;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;

/**

  • @Description : 提供一些常用的工具方法

  • @Date : 2018-08-14 05:51 */ public class Utils { private static final Logger logger = LoggerFactory.getLogger(Utils.class);

    /**

    • 列印當前執行緒堆疊資訊

    • @param prefix */ public static void printTrack(String prefix){ StackTraceElement[] st = Thread.currentThread().getStackTrace();

      if(null==st){ logger.info(“invalid stack”); return; }

      StringBuffer sbf =new StringBuffer();

      for(StackTraceElement e:st){ if(sbf.length()>0){ sbf.append(" <- "); sbf.append(System.getProperty(“line.separator”)); }

       sbf.append(java.text.MessageFormat.format("{0}.{1}() {2}"
               ,e.getClassName()
               ,e.getMethodName()
               ,e.getLineNumber()));
      

      }

      logger.info(prefix + “\n************************************************************\n” + sbf.toString() + “\n************************************************************”); } }

  1. 新建類CustomizeBeanNameAware,實現BeanNameAware介面,方法setBeanName被呼叫的時候會列印當前堆疊資訊:

package com.bolingcavalry.customizeaware.aware;

import com.bolingcavalry.customizeaware.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanNameAware; import org.springframework.stereotype.Service;

/**

  • @Description :

  • @Date : 2018-08-13 18:55 */ @Service public class CustomizeBeanNameAware implements BeanNameAware { private String beanName;

    @Override public void setBeanName(String beanName) { Utils.printTrack("beanName is set to " + beanName); this.beanName = beanName; }

    public String getBeanName() { return this.beanName; } }

  1. 新建類CustomizeApplicationContextAware,實現ApplicationContextAware介面,方法setApplicationContext被呼叫的時候會列印當前堆疊資訊::

package com.bolingcavalry.customizeaware.aware;

import com.bolingcavalry.customizeaware.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service;

/**

  • @Description :

  • @Date : 2018-08-13 19:01 */ @Service public class CustomizeApplicationContextAware implements ApplicationContextAware { private ApplicationContext applicationContext;

    @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Utils.printTrack("applicationContext is set to " + applicationContext); this.applicationContext = applicationContext; }

    public ApplicationContext getApplicationContext(){ return this.applicationContext; } }

  1. 新建一個Controller,提供http服務用於驗證CustomizeBeanNameAware和CustomizeApplicationContextAware這兩個bean,看看它們被spring容器設定的beanName和applicationContext是否可用:

package com.bolingcavalry.customizeaware.controller;

import com.bolingcavalry.customizeaware.aware.CustomizeApplicationContextAware; import com.bolingcavalry.customizeaware.aware.CustomizeBeanNameAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**

  • @Description :

  • @Date : 2018-08-13 19:04 */ @RestController public class HelloWorldController {

    @Autowired private CustomizeBeanNameAware customizeBeanNameAware;

    @Autowired private CustomizeApplicationContextAware customizeApplicationContextAware;

    @RequestMapping("/hello") public String hello(){

     String[] beanDefinitionNames = customizeApplicationContextAware.getApplicationContext().getBeanDefinitionNames();
    
     StringBuilder stringBuilder = new StringBuilder();
    
     int arrayLength = 0;
    
     if(null!=beanDefinitionNames){
         arrayLength = beanDefinitionNames.length;
         //將所有bean的名稱拼接成字串(帶html的換行符號<br>)
         for(String name : beanDefinitionNames){
             stringBuilder.append(name).append("<br>");
         }
     }
    
     return "hello, "
             + new Date()
             + "<br><br>CustomizeBeanNameAware instance bean name : "
             + customizeBeanNameAware.getBeanName()
             + "<br><br>bean definition names, size "
             + arrayLength
             + ", detail :<br><br>"
             + stringBuilder;
    

    }

}

  1. 啟動應用,看到啟動日誌中帶有CustomizeBeanNameAware和CustomizeApplicationContextAware的介面方法被呼叫時輸出的日誌,並且執行緒堆疊和我們之前看的spring原始碼位置一致,分別是ApplicationContextAwareProcessor.invokeAwareInterfaces()和AbstractAutowireCapableBeanFactory.invokeAwareMethods():

C:\jdk\bin\java.exe -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=63257 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=localhost -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:C:\software\JetBrains\IntelliJIDEA\lib\idea_rt.jar=63258:C:\software\JetBrains\IntelliJIDEA\bin -Dfile.encoding=UTF-8 -classpath C:\jdk\jre\lib\charsets.jar;C:\jdk\jre\lib\deploy.jar;C:\jdk\jre\lib\ext\access-bridge-64.jar;C:\jdk\jre\lib\ext\cldrdata.jar;C:\jdk\jre\lib\ext\dnsns.jar;C:\jdk\jre\lib\ext\jaccess.jar;C:\jdk\jre\lib\ext\jfxrt.jar;C:\jdk\jre\lib\ext\localedata.jar;C:\jdk\jre\lib\ext\nashorn.jar;C:\jdk\jre\lib\ext\sunec.jar;C:\jdk\jre\lib\ext\sunjce_provider.jar;C:\jdk\jre\lib\ext\sunmscapi.jar;C:\jdk\jre\lib\ext\sunpkcs11.jar;C:\jdk\jre\lib\ext\zipfs.jar;C:\jdk\jre\lib\javaws.jar;C:\jdk\jre\lib\jce.jar;C:\jdk\jre\lib\jfr.jar;C:\jdk\jre\lib\jfxswt.jar;C:\jdk\jre\lib\jsse.jar;C:\jdk\jre\lib\management-agent.jar;C:\jdk\jre\lib\plugin.jar;C:\jdk\jre\lib\resources.jar;C:\jdk\jre\lib\rt.jar;D:\github\blog_demos\customizeaware\target\classes;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-starter-web\2.0.4.RELEASE\spring-boot-starter-web-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-starter\2.0.4.RELEASE\spring-boot-starter-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot\2.0.4.RELEASE\spring-boot-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.0.4.RELEASE\spring-boot-autoconfigure-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.0.4.RELEASE\spring-boot-starter-logging-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\12167.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\12167.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.10.0\log4j-to-slf4j-2.10.0.jar;C:\Users\12167.m2\repository\org\apache\logging\log4j\log4j-api\2.10.0\log4j-api-2.10.0.jar;C:\Users\12167.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\12167.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\12167.m2\repository\org\yaml\snakeyaml\1.19\snakeyaml-1.19.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-starter-json\2.0.4.RELEASE\spring-boot-starter-json-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.6\jackson-databind-2.9.6.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.6\jackson-core-2.9.6.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.6\jackson-datatype-jdk8-2.9.6.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.6\jackson-datatype-jsr310-2.9.6.jar;C:\Users\12167.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.6\jackson-module-parameter-names-2.9.6.jar;C:\Users\12167.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.0.4.RELEASE\spring-boot-starter-tomcat-2.0.4.RELEASE.jar;C:\Users\12167.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.32\tomcat-embed-core-8.5.32.jar;C:\Users\12167.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.32\tomcat-embed-el-8.5.32.jar;C:\Users\12167.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.32\tomcat-embed-websocket-8.5.32.jar;C:\Users\12167.m2\repository\org\hibernate\validator\hibernate-validator\6.0.11.Final\hibernate-validator-6.0.11.Final.jar;C:\Users\12167.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\12167.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\12167.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\12167.m2\repository\org\springframework\spring-web\5.0.8.RELEASE\spring-web-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-beans\5.0.8.RELEASE\spring-beans-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-webmvc\5.0.8.RELEASE\spring-webmvc-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-aop\5.0.8.RELEASE\spring-aop-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-context\5.0.8.RELEASE\spring-context-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-expression\5.0.8.RELEASE\spring-expression-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\12167.m2\repository\org\springframework\spring-core\5.0.8.RELEASE\spring-core-5.0.8.RELEASE.jar;C:\Users\12167.m2\repository\org\springframework\spring-jcl\5.0.8.RELEASE\spring-jcl-5.0.8.RELEASE.jar com.bolingcavalry.customizeaware.CustomizeawareApplication

. ____ _ __ _ _ /\ / __ _ () __ __ _ \ \ \ ( ( )__ | '_ | '| | ’ / ` | \ \ \ \/ )| |)| | | | | || (| | ) ) ) ) ’ || .__|| ||| |__, | / / / / =|_|======|/=//// :: Spring Boot :: (v2.0.4.RELEASE)

2018-08-14 06:07:11.512 INFO 18940 — [ main] c.b.c.CustomizeawareApplication : Starting CustomizeawareApplication on DESKTOP-82CCEBN with PID 18940 (D:\github\blog_demos\customizeaware\target\classes started by 12167 in D:\github\blog_demos\customizeaware) 2018-08-14 06:07:11.514 INFO 18940 — [ main] c.b.c.CustomizeawareApplication : No active profile set, falling back to default profiles: default 2018-08-14 06:07:11.546 INFO 18940 — [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.ser[email protected]6ab7a896: startup date [Tue Aug 14 06:07:11 GMT+08:00 2018]; root of context hierarchy 2018-08-14 06:07:12.165 INFO 18940 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2018-08-14 06:07:12.177 INFO 18940 — [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-08-14 06:07:12.177 INFO 18940 — [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.32 2018-08-14 06:07:12.180 INFO 18940 — [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [C:\jdk\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Program Files (x86)\Intel\Intel® Management Engine Components\iCLS;C:\Program Files\Intel\Intel® Management Engine Components\iCLS;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0;C:\Program Files (x86)\Intel\Intel® Management Engine Components\DAL;C:\Program Files\Intel\Intel® Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel® Management Engine Components\IPT;C:\Program Files\Intel\Intel® Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\jdk\bin;C:\software\Git\cmd;C:\software\apache-maven-3.5.0\bin;;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0;%SYSTEMROOT%\System32\OpenSSH;C:\Users\12167\AppData\Local\Microsoft\WindowsApps;;.] 2018-08-14 06:07:12.244 INFO 18940 — [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-08-14 06:07:12.244 INFO 18940 — [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 700 ms 2018-08-14 06:07:12.281 INFO 18940 — [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/] 2018-08-14 06:07:12.284 INFO 18940 — [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ‘characterEncodingFilter’ to: [/] 2018-08-14 06:07:12.284 INFO 18940 — [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ‘hiddenHttpMethodFilter’ to: [/] 2018-08-14 06:07:12.284 INFO 18940 — [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ‘httpPutFormContentFilter’ to: [/] 2018-08-14 06:07:12.285 INFO 18940 — [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ‘requestContextFilter’ to: [/] 2018-08-14 06:07:12.305 INFO 18940 — [ main] c.b.customizeaware.util.Utils : applicationContext is set to org.springframework.boot.web.ser[email protected]6ab7a896: startup date [Tue Aug 14 06:07:11 GMT+08:00 2018]; root of context hierarchy

java.lang.Thread.getStackTrace() 1,559 <- com.bolingcavalry.customizeaware.util.Utils.printTrack() 20 <- com.bolingcavalry.customizeaware.aware.CustomizeApplicationContextAware.setApplicationContext() 22 <- org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces() 120 <- org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization() 96 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization() 416 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,691 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 573 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 495 <- org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0() 317 <- org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 222 <- org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 315 <- org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 199 <- org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 759 <- org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 869 <- org.springframework.context.support.AbstractApplicationContext.refresh() 550 <- org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh() 140 <- org.springframework.boot.SpringApplication.refresh() 762 <- org.springframework.boot.SpringApplication.refreshContext() 398 <- org.springframework.boot.SpringApplication.run() 330 <- org.springframework.boot.SpringApplication.run() 1,258 <- org.springframework.boot.SpringApplication.run() 1,246 <- com.bolingcavalry.customizeaware.CustomizeawareApplication.main() 10

2018-08-14 06:07:12.307 INFO 18940 — [ main] c.b.customizeaware.util.Utils : beanName is set to customizeBeanNameAware

java.lang.Thread.getStackTrace() 1,559 <- com.bolingcavalry.customizeaware.util.Utils.printTrack() 20 <- com.bolingcavalry.customizeaware.aware.CustomizeBeanNameAware.setBeanName() 20 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods() 1,712 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean() 1,686 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean() 573 <- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean() 495 <- org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0() 317 <- org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton() 222 <- org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean() 315 <- org.springframework.beans.factory.support.AbstractBeanFactory.getBean() 199 <- org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons() 759 <- org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization() 869 <- org.springframework.context.support.AbstractApplicationContext.refresh() 550 <- org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh() 140 <- org.springframework.boot.SpringApplication.refresh() 762 <- org.springframework.boot.SpringApplication.refreshContext() 398 <- org.springframework.boot.SpringApplication.run() 330 <- org.springframework.boot.SpringApplication.run() 1,258 <- org.springframework.boot.SpringApplication.run() 1,246 <- com.bolingcavalry.customizeaware.CustomizeawareApplication.main() 10

2018-08-14 06:07:12.359 INFO 18940 — [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [//favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-08-14 06:07:12.474 INFO 18940 — [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.ser[email protected]6ab7a896: startup date [Tue Aug 14 06:07:11 GMT+08:00 2018]; root of context hierarchy 2018-08-14 06:07:12.507 INFO 18940 — [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped “{[/hello]}” onto public java.lang.String com.bolingcavalry.customizeaware.controller.HelloWorldController.hello() 2018-08-14 06:07:12.511 INFO 18940 — [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped “{[/error]}” onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2018-08-14 06:07:12.511 INFO 18940 — [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped “{[/error],produces=[text/html]}” onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2018-08-14 06:07:12.524 INFO 18940 — [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-08-14 06:07:12.524 INFO 18940 — [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-08-14 06:07:12.602 INFO 18940 — [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-08-14 06:07:12.622 INFO 18940 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ‘’ 2018-08-14 06:07:12.625 INFO 18940 — [ main] c.b.c.CustomizeawareApplication : Started CustomizeawareApplication in 1.311 seconds (JVM running for 1.932)

本章實戰的原始碼可以在github下載,地址和連結資訊如下表所示: 名稱 連結 備註 專案主頁 https://github.com/zq2599/blog_demos 該專案在GitHub上的主頁 git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該專案原始碼的倉庫地址,https協議 git倉庫地址(ssh) [email protected]:zq2599/blog_demos.git 該專案原始碼的倉庫地址,ssh協議

這個git專案中有多個資料夾,本章原始碼在資料夾customizeaware/下,如下圖紅框所示: 這裡寫圖片描述

至此,spring的Aware介面實戰就結束了,由於篇幅所限,本章只選擇了BeanNameAware和ApplicationContextAware這兩個介面來實戰,您可以結合spring原始碼去分析其他Aware介面的用處,再在demo用去驗證它們;