结论先行
1。自定义组件如果想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);只需要自定义组件实现xxxAware,并实现相应的方法,在创建对象的时候,Spring会调用接口规定的方法注入相关组件;
2.Spring通过使用xxxAwareProcessor处理实现xxxAware接口想要使用相应的底层组件的bean注入。比如ApplicationContextAware接口就是使用ApplicationContextAwareProcessor处理器处理注入IOC容器
接口定义
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory;
/**
* Marker superinterface indicating that a bean is eligible to be
* notified by the Spring container of a particular framework object
* through a callback-style method. Actual method signature is
* determined by individual subinterfaces, but should typically
* consist of just one void-returning method that accepts a single
* argument.
*
* <p>Note that merely implementing {@link Aware} provides no default
* functionality. Rather, processing must be done explicitly, for example
* in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
* and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
* for examples of processing {@code *Aware} interface callbacks.
*
* @author Chris Beams
* @since 3.1
*/
public interface Aware {
}
解释
类似与函数回调的方式,让框架可以使用spring的一些bean
接口及其子类
bean定义
package com.ouyangxizhu;
import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.bean.Red;
import com.ouyangxizhu.config.MainConfigXXXAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTestXXXAware {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigXXXAware.class);
Red bean = context.getBean(Red.class);
System.out.println(bean.getApplicationContext() == context);
}
}
配置类
package com.ouyangxizhu.config;
import com.ouyangxizhu.bean.Red;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MainConfigXXXAware {
@Bean
public Red red(){
return new Red();
}
}
启动类
package com.ouyangxizhu;
import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.bean.Red;
import com.ouyangxizhu.config.MainConfigXXXAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTestXXXAware {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigXXXAware.class);
Red bean = context.getBean(Red.class);
System.out.println(bean.getApplicationContext() == context);
}
}
结果
八月 06, 2020 3:48:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Thu Aug 06 15:48:07 CST 2020]; root of context hierarchy
八月 06, 2020 3:48:08 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
当前bean的名字:red
解析的字符串:你好 Mac OS X 我是 121
传入的ioc:org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Thu Aug 06 15:48:07 CST 2020]; root of context hierarchy
true
结果说明
通过XXXAware接口,我们可以使用一些Spring的内置bean
原理
在red的setApplicationContext方法打断点,以debug方式运行
可以查看调用栈如下
1)初始化容器时调用
org.springframework.context.support.AbstractApplicationContext#refresh方法,刷新容器
2)在refres()的12个方法中会调用org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization这个方法,这个方法注释说// Instantiate all remaining (non-lazy-init) singletons.,即初始化其余的非懒加载单例bean
3)上面方法在进行一些beanFactory的检查和beanFactory属性赋值后调用beanFactory的org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons方法,进行真正的始化其余的非懒加载单例bean
4)调用org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)方法获取bean
5)调用org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法,真正获取bean
6)判断是单例bean会尝试 获取单例bean,org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
7)尝试从singletonFactory单例工厂中的缓存获取,如果没有会创建一个新的bean,即singletonObject = singletonFactory.getObject();
org.springframework.beans.factory.ObjectFactory#getObject
8)由于缓存中没有会创建bean。org.springframework.beans.factory.support.AbstractBeanFactory#createBean
9)真正创建bean。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
10)创建bean之后会调用其初始化方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
11)初始化方法中有下面的片段
1.调用BeanPostProcessors中的BeforeInitialization方法
2.再对bean进行初始化
3.再调用BeanPostProcessorsAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
应用BeanPostProcessor的初始化前后方法其实就是获取所有的BeanPostProcessor并调用其相应的初始化前后方法。
12)在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization方法中,会调用org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization这个方法,即调用所有的BeanPostProcessor的postProcessBeforeInitialization方法,注意ApplicationContextAwareProcessor是BeanPostProcessor的实现类
13 在ApplicationContextAwareProcessor中调用org.springframework.context.support.ApplicationContextAwareProcessor#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(this.embeddedValueResolver);
}
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是否实现了相应接口,实现的话就调用相应的方法