spring4.1.8 扩展实战之二:Aware 接口揭秘
- 2022 年 6 月 13 日
本文字数:12782 字
阅读完需:约 42 分钟
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
Aware.java 是个没有定义任何方法的接口,拥有众多子接口,在 spring 源码中有多处都在使用这些子接口完成各种场景下的回调操作,当业务有需要时,我们只需创建类来实现相关接口,再声明为 bean,就可以被 spring 容器主动回调;
spring 源码分析 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 这两个接口,看声明的方法是否能被调用,并验证传入的对象是否有效(文章结尾处提供本次实战的工程源码下载);
基于 maven 新建一个 SpringBoot 的 web 工程 customizeaware;
新建工具类 Utils,提供静态方法 printTrack 用于打印当前线程堆栈信息:
package com.bolingcavalry.customizeaware.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @Description : 提供一些常用的工具方法
* @Author : zq2599@gmail.com
* @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************************************************************");
}
}
新建类 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 :
* @Author : zq2599@gmail.com
* @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;
}
}
新建类 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 :
* @Author : zq2599@gmail.com
* @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;
}
}
新建一个 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 :
* @Author : zq2599@gmail.com
* @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;
}
}
启动应用,看到启动日志中带有 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.servlet.context.AnnotationConfigServletWebServerApplicationContext@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(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) 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(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) 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.servlet.context.AnnotationConfigServletWebServerApplicationContext@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.servlet.context.AnnotationConfigServletWebServerApplicationContext@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)
浏览器访问 web 服务,地址:http://localhost:8080/hello,如下图,两个实现了 Aware 接口的 bean 的被设置的信息都打印出来了,都是来自 spring 环境的内容:
验证结束,自定义的 Aware 接口实现类如果声明为 bean,在初始化的时候就会被 spring 容器按照接口类型找出来,通过调用接口方法的方式将特定的对象实例传递给 bean;
实战源码下载
本章实战的源码可以在 github 下载,地址和链接信息如下表所示:
这个 git 项目中有多个文件夹,本章源码在文件夹 customizeaware/下,如下图红框所示:
至此,spring 的 Aware 接口实战就结束了,由于篇幅所限,本章只选择了 BeanNameAware 和 ApplicationContextAware 这两个接口来实战,您可以结合 spring 源码去分析其他 Aware 接口的用处,再在 demo 用去验证它们;
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/1b7f3ee4f70b3ad95f7939dc3】。文章转载请联系作者。
程序员欣宸
搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入
前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos
评论