public class BeanMetadataConfigurationDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 实例化基于 Properties 资源 BeanDefinitionReader
PropertiesBeanDefinitionReader beanDefinitionReader = new PropertiesBeanDefinitionReader(beanFactory);
String location = "META-INF/user.properties";
// 基于 ClassPath 加载 properties 资源
Resource resource = new ClassPathResource(location);
// 指定字符编码 UTF-8
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
System.out.println("已加载 BeanDefinition 数量:" + beanNumbers);
// 通过 Bean Id 和类型进行依赖查找
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
}
}
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 基于 Java 注解的 AnnotatedBeanDefinitionReader 的实现
AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(beanFactory);
int beanDefinitionCountBefore = beanFactory.getBeanDefinitionCount();
// 注册当前类(非 @Component class)
beanDefinitionReader.register(AnnotatedBeanDefinitionParsingDemo.class);
int beanDefinitionCountAfter = beanFactory.getBeanDefinitionCount();
int beanDefinitionCount = beanDefinitionCountAfter - beanDefinitionCountBefore;
System.out.println("已加载 BeanDefinition 数量:" + beanDefinitionCount);
// 普通的 Class 作为 Component 注册到 Spring IoC 容器后,通常 Bean 名称为 annotatedBeanDefinitionParsingDemo
// Bean 名称生成来自于 BeanNameGenerator,注解实现 AnnotationBeanNameGenerator
AnnotatedBeanDefinitionParsingDemo demo = beanFactory.getBean("annotatedBeanDefinitionParsingDemo",
AnnotatedBeanDefinitionParsingDemo.class);
System.out.println(demo);
}
注册的类并不一定非要标注@Component
AnnotatedBeanDefinitionReader并未实现BeanDefinitionReader.因为他不知道通过其他资源读取,直接通过register方法进行注册.
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
在这个方法中有最中有最重要的2个属性beanDefinitionMap和beanDefinitionNames
beanDefinitionMap:用户保存beanDefinition的实例对象
beanDefinitionNames:用户保存注册进beanDefinitionMap的顺序
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
这里的updatedDefinitions 是非线程安全的,可以减少一些线程重进入的计算。
public class MergedBeanDefinitionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 基于 XML 资源 BeanDefinitionReader 实现
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String location = "META-INF/dependency-lookup-context.xml";
// 基于 ClassPath 加载 XML 资源
Resource resource = new ClassPathResource(location);
// 指定字符编码 UTF-8
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
System.out.println("已加载 BeanDefinition 数量:" + beanNumbers);
// 通过 Bean Id 和类型进行依赖查找
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
User superUser = beanFactory.getBean("superUser", User.class);
System.out.println(superUser);
}
}
Root BeanDefinition 不需要合并,不存在 parent
普通 beanDefinition GenericBeanDefinition 合并后 GenericBeanDefinition 变成 RootBeanDefinition,并且覆盖 parent 相关配置
总结 AbstractBeanFactory#resolveBeanClass中将string类型的beanClass 通过当前线程Thread.currentThread().getContextClassLoader(),Class.forName来获取class对象,将beanClass变为Class类型对象
最终是采用反射的newInstance实例化的,
class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
// 把配置完成 superUser Bean 覆盖
return new SuperUser();
}
return null; // 保持 Spring IoC 容器的实例化操作
}
}
最后的结论构造器注入时按照类型注入存在点歧义,应该是先按照类型在按照名称;当superUser的primary给去掉时,此时根据User类型查找时会找到两个匹配的bean对象,user和superUser在选择候选bean时是按照 primary bean->resolveDependency包含->beanName和descriptor.getDependencyName()相等的bean,当无primary bean是选择则是从user和superUser中选择的user,因为user bean的名称和userHolder注入的user名称相等
class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
User user = (User) bean;
user.setId(2L);
user.setName("mercyblitz");
// "user" 对象不允许属性赋值(填入)(配置元信息 -> 属性值)
return false;
}
return true;
}
}
在bean实例化之后可以通过InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation设置Bean中的初始值并返回
总结InstantiationAwareBeanPostProcessor方法:
postProcessBeforeInstantiation()在bean实例化前回调,返回实例则不对bean实例化,返回null则进行spring bean实例化(doCreateBean);
postProcessAfterInstantiation()在bean实例化后在填充bean属性之前回调,返回true则进行下一步的属性填充,返回false:则不进行属性填充
postProcessProperties在属性赋值前的回调在applyPropertyValues之前操作可以对属性添加或修改等操作最后在通过applyPropertyValues应用bean对应的wapper对象
在执行完org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean方法填充完属性后,在initializeBean中调用invokeAwareMethods
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
此处会执行 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware三个接口的方法.如果只是普通的BeanFactory只支持这3个aware接口.
后面其他的aware是数据ApplicationContext生命周期里面的…
在applicationContext中的refresh()方法中->prepareBeanFactory()->
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
ApplicationContextAwareProcessor 中实现的aware
private void invokeAwareInterfaces(Object bean) {
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);
}
}
由于ApplicationContextAwareProcessor是一个内置类的关系,在ApplicationContext初始化的时候会动态的添加一个BeanPostProcessor(ApplicationContextAwareProcessor).
由此可见对于Aware接口的支持也是一个BeanFactory和ApplicationContext的区别.
BeanFactory只支持BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 3个.
ApplicationContext支持多有的Aware.
通过XmlBeanDefinitionReader loadBeanDefinitions是将xml中bean对应的beanDefinition注册到beanFactory中,底层通过BeanDefinitionReaderUtils#registerBeanDefinition()方法实现,这个在BeanDefinition注册阶段讲过,这个时候只是注册beanDefinition没有像ApplicationContext.refresh()中的registerBeanPostProcessors()将bean post Processor添加到beanFactory的beanPostProcessors list集合中操作,所以xml读取的时候需要手动的addBeanPostProcessor;如果通过ClassPathXmlApplicationContext创建ApplicationContext的方式xml中定义MyInstantiationAwareBeanPostProcessor是可以的,因为ClassPathXmlApplicationContext创建时会执行refresh()操作会从beanFactory中找到MyInstantiationAwareBeanPostProcessor bean后添加到beanPostProcessors的list集合中
1.在bean初始化前阶段initializeBean()对应的applyBeanPostProcessorsBeforeInitialization()方法中执行完自定义的MyInstantiationAwareBeanPostProcessor的postProcessBeforeInitialization()方法同时会执行CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization方法最后执行@PostConstruct修饰的initPostConstructor方法
2.其他两种bean初始化在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods()中被调用
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization完成@PostConstruct方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 实现 afterPropertiesSet 和 自定义初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction
在填充bean属性完成之后initializeBean()中有四个过程
1.aware的接口回调(不包括ApplicationContext相关)
2.postProcessBeforeInitialization()包括两部分关于ApplicationContextAwareProcessor的aware接口回调和自定义bean post processor的postProcessBeforeInitialization回调和@PostConstruct标识方法(CommonAnnotationBeanPostProcessor中)
3.invokeInitMethods() bean初始化的回调比如实现InitializingBean接口
4.applyBeanPostProcessorsAfterInitialization() bean初始化之后的回调
ApplicationContext在refresh的操作里等beanFactory的一系列操作,messageSource,注册listener等操作都完毕之后通过finishBeanFactoryInitialization开始实例化所有非懒加载的单例bean,具体是在finishBeanFactoryInitialization调用beanFactory#preInstantiateSingletons进行的,preInstantiateSingletons里面就是通过beanDefinitionNames循环调用getBean来实例化bean的,这里有个细节,beanDefinitionNames是拷贝到一个副本中,循环副本,使得还能注册新的beanDefinition.
getBean的操作就是我们之前那么多节课分析的一顿操作的过程,最终得到一个完整的状态的bean。 然后所有的非延迟单例都加载完毕之后,再重新循环副本,判断bean是否是SmartInitializingSingleton,如果是的话执行SmartInitializingSingleton#afterSingletonsInstantiated。这保证执行afterSingletonsInstantiated的时候的bean一定是完整的。
destroyBean 操作仅是触发 Bean 销毁生命周期,因为 Bean 有可能再次被初始化,比如显示地调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.Object, java.lang.String) 方法
其中@PreDestory是在CommonAnnotationBeanPostProcessor中处理的.处于最先的阶段.
总结:beanFactory处理bean的过程
1.注册bean Definition registerBeanDefinition()
2.bean Definition的合并阶段 getMergedLocalBeanDefinition(),比如user和superUser 最后都变为root bean Definition
3.创建bean createBean()
4.将bean类型从string变为class类型 resolveBeanClass()
5.bean实例化前工作resolveBeforeInstantiation(),比如可以返回自定义的bean对象让spring不在实例化bean对象
6.开始实例化bean doCreateBean()
7.实例化bean createBeanInstance()
8.bean实例化后 postProcessAfterInstantiation()返回false即bean不在对属性处理
9.属性赋值前对属性处理postProcessProperties()
10.属性赋值applyPropertyValues()
11.bean初始化阶段initializeBean()
12.初始化前aware接口回调(非ApplicationContextAware),比如beanFactoryAware
13.初始化前回调applyBeanPostProcessorsBeforeInitialization(),比如@PostConstructor
14.初始化invokeInitMethods(),比如实现InitializingBean接口的afterPropertiesSet()方法回调
15.初始化后的回调applyBeanPostProcessorsAfterInitialization()
16.bean重新的填充覆盖来更新bean preInstantiateSingletons()
17.bean销毁前postProcessBeforeDestruction()
18.bean销毁,比如@PreDestroy