spring4.1.8扩展实战之二:Aware接口揭秘

Aware.java是个没有定义任何方法的接口,拥有众多子接口,在spring源码中有多处都在使用这些子接口完成各种场景下的回调操作,当业务有需要时,我们只需创建类来实现相关接口,再声明为bean,就可以被spring容器主动回调;

原文地址:https://blog.csdn.net/boling_cavalry/article/details/81611426

spring源码分析Aware子类的使用场景

接下来通过分析spring源码,我们来看看典型的Aware子类有哪些,使用场景是什么?

  1. 在spring容器初始化过程中,会执行AbstractApplicationContext类的prepareBeanFactory方法,这里面会创建一个bean后置处理器ApplicationContextAwareProcessor,如下图红框所示:
    这里写图片描述

  2. 在bean被初始化之前,所有的bean后置处理器的postProcessBeforeInitialization方法都会被执行,如下图红框所示:
    这里写图片描述

  3. 由以上两步可以确定:对于每个bean后置处理器来说,它的postProcessBeforeInitialization方法会在每个bean的初始化之前被调用一次;

  4. 来看看ApplicationContextAwareProcessor类的postProcessBeforeInitialization方法,按照前面的分析,该方法在每个bean被初始化之前都会被执行,如下图红框所示,invokeAwareInterfaces方法会被调用,这是我们要关注的重点:
    这里写图片描述

  5. 展开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方法中,我们来看看它是如何被调用的;

  1. 如下图所示,红框中就是BeanNameAware接口被调用的地方,而绿框中的applyBeanPostProcessorsBeforeInitialization方法就是前面我们分析的那些Aware子接口被调用的位置:
    这里写图片描述

  2. 方法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 : 提供一些常用的工具方法
 * @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************************************************************");
    }
}


3. 新建类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;
    }
}


4. 新建类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;
    }
}


5. 新建一个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;
    }


}


6. 启动应用,看到启动日志中带有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)


7. 浏览器访问web服务,地址:http://localhost:8080/hello,如下图,两个实现了Aware接口的bean的被设置的信息都打印出来了,都是来自spring环境的内容:
这里写图片描述

8. 验证结束,自定义的Aware接口实现类如果声明为bean,在初始化的时候就会被spring容器按照接口类型找出来,通过调用接口方法的方式将特定的对象实例传递给bean;

实战源码下载

本章实战的源码可以在github下载,地址和链接信息如下表所示:

名称链接备注
项目主页https://github.com/zq2599/blog_demos该项目在GitHub上的主页
git仓库地址(https)https://github.com/zq2599/blog_demos.git该项目源码的仓库地址,https协议
git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本章源码在文件夹customizeaware/下,如下图红框所示:
这里写图片描述

至此,spring的Aware接口实战就结束了,由于篇幅所限,本章只选择了BeanNameAware和ApplicationContextAware这两个接口来实战,您可以结合spring源码去分析其他Aware接口的用处,再在demo用去验证它们;

《spring4.1.8扩展实战》系列文章链接:
1. 《spring4.1.8扩展实战之一:自定义环境变量验证》;
2. 《spring4.1.8扩展实战之二:Aware接口揭秘》;
3. 《spring4.1.8扩展实战之三:广播与监听》;
4. 《spring4.1.8扩展实战之四:感知spring容器变化(SmartLifecycle接口)》;
5. 《spring4.1.8扩展实战之五:改变bean的定义(BeanFactoryPostProcessor接口)》;
6. 《spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)》;
7. 《spring4.1.8扩展实战之七:控制bean(BeanPostProcessor接口)》;

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页