初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource
Posted 做猪呢,最重要的是开森啦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource相关的知识,希望对你有一定的参考价值。
0. 栗子:
@Component
public class SetterBean implements BeanNameAware, InitializingBean {
private String beanName;
@Resource(name = "beanService1")
private BeanService beanService;
@Override
public void setBeanName(String name) {
beanName = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("SetterBean run afterPropertiesSet");
}
@PostConstruct
public void testPostConstruct() {
System.out.println("SetterBean run PostConstruct");
System.out.println("this beanName : " + beanName);
}
}
@Configuration
public class ConfigurationBean {
@Bean(initMethod = "initMethodTest")
public BeanServiceInitMethod beanService1() {
return new BeanServiceInitMethod();
}
@Bean
public BeanService beanService() {
BeanServiceImpl beanService = new BeanServiceImpl();
beanService.setName("zhangsan");
return beanService;
}
}
@Component
public class BeanServiceInitMethod implements BeanService {
private String name;
public void initMethodTest() throws Exception {
System.out.println("BeanServiceInitMethod run initMethodTest");
}
}
4.1 initializeBean:
上一篇文章介绍了bean生命周期的属性填充populateBean方法的一些细节,至此,doCreateBean经历以下步骤:
- bean的实例化:createBeanInstance
- applyMergedBeanDefinitionPostProcessors进行属性和方法的预解析
- addSingletonFactory引入三级缓存
- populateBean属性填充
- bean的初始化:initializeBean
bean的初始化,整体包括下方添加注释的四点
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 4.1. 调用Aware扩展接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 4.2. 引用初始化前后置处理器,@PostConstruct的方法便是此处调用的
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 4.3. 调用初始化方法,afterPropertiesSet方法便是此处调用
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()) {
// 4.4. 引用初始化后后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
4.1. invokeAwareMethods:
为了让我们的bean可以感知到容器内的一些东西,所以Spring为我们提供了Aware接口
`
这里分别是让bean能够感知到beanName、ClassLoader、BeanFactory
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
// 实现BeanNameAware接口的类可以感知到beanName
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
// 实现BeanClassLoaderAware接口的类可以感知到beanClassLoader
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
// 实现BeanFactoryAware接口的类可以感知到BeanFactory
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
像本栗子SetterBean是实现了BeanNameAware,SetterBean便可以感知到beanName,像本栗子只是简单赋值。
4.2. applyBeanPostProcessorsBeforeInitialization:
调用所有BeanPostProcessor 的 postProcessBeforeInitialization 方法,来对bean进行初始化前处理
·
好比常用的@PostConstruct便是此处进行调用的,详情见下文4.6
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 调用postProcessBeforeInitialization方法来对bean进行初始化前处理
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
4.3. invokeInitMethods:
开始执行bean的初始化方法,主要处理afterPropertiesSet和initMethod
- 如果要初始化的bean实现了InitializingBean接口,就会去调用afterPropertiesSet方法;像本栗子的SetterBean
- 如果像xml配置init-method,或者本栗中beanService1的@Bean(initMethod = “initMethodTest”),则取执行指定自定义初始化方法
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 判断初始化的bean是不是实现了InitializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
// 实现了InitializingBean接口&&重写了afterPropertiesSet方法
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
// 这个getSecurityManager一直不知道是什么,默认都不会走这里
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
// 执行bean重写的afterPropertiesSet方法
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 初始化的bean没有实现了InitializingBean接口,像本栗子beanService1这个bean
if (mbd != null && bean.getClass() != NullBean.class) {
// 获取bean的初始化方法名
String initMethodName = mbd.getInitMethodName();
// 存在初始化方法&&
// (没有实现了InitializingBean接口&&初始化方法名不是afterPropertiesSet&&是外部管理的初始化方法)
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 执行自定义的初始化方法,像本栗子的initMethodTest方法
// 如果初始化方法名为空则默认抛异常,否则通过反射来调用自定义的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
4.4. applyBeanPostProcessorsAfterInitialization:
调用所有BeanPostProcessor 的 postProcessAfterInitialization 方法,来对bean进行初始化后处理
·
这里如果有AOP会进行代理对象的处理,后面再介绍
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
4.5. @Resource:
在之前的文章2.3节中介绍了@Autowired注入过程,@Resource其实也类似,主要有以下步骤
4.5.1. 封装注入属性元数据metadata:
关于标注 @Resource的属性元数据封装,可以查看文章1.2节内容
4.5.2. CommonAnnotationBeanPostProcessor#postProcessProperties:
在属性填充时,调用后置处理器的postProcessProperties方法进行注入
·
处理@Resource的后置处理器是CommonAnnotationBeanPostProcessor
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 对@Resource标注的属性/方法的元数据之前就预解析封装了,这里可以直接获取
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
// 根据属性方法元数据metadata,进行注入
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
4.5.3. metadata.inject:
属性和方法元数据封装到ResourceElement,最后都封装到InjectionMetadata
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
循环遍历属性、方法元数据进行注入;同@Autowired一样会先进行属性注入,再进行方法注入。
4.5.4. element.inject:
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
// 属性注入的处理
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
// 直接反射进行注入,重点方法getResourceToInject获取注入的属性实例
field.set(target, getResourceToInject(target, requestingBeanName));
}
// 方法注入的处理
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
4.5.5. getResourceToInject:
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
// 如果标注@,Resource的属性/方法,还标注了@Lazy即懒加载的,则lazyLookup=true,通过代理获取注入属性的实例
// 否则通过getResource方法进行获取
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
4.5.6. getResource:
默认mappedName为空,alwaysUseJndiLookup为false
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
if (StringUtils.hasLength(element.mappedName)) {
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
if (this.alwaysUseJndiLookup) {
return this.jndiFactory.getBean(element.name, element.lookupType);
}
// 上面是jndi的处理,默认是不会走的,除非注解设置了lookup或mappedName属性
// resourceFactory不为空,默认是DefaultListableBeanFactory类型
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the 'resourceFactory' property");
}
// 默认是走这个方法获取实例
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
4.5.7. autowireResource:
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
// 注解中name属性值,不写name则默认是注入的属性名
String name = element.name;
// DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory 默认条件成立
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
// 封装依赖描述器DependencyDescriptor
DependencyDescriptor descriptor = element.getDependencyDescriptor();
// fallbackToDefaultTypeMatch默认true&&注解不写name属性&&工厂不包含属性名的bean
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
autowiredBeanNames = new LinkedHashSet<>();
// 条件成立则通过resolveDependency获取实例,在第三篇文章接介绍过
// 一般我们都会指定name属性,所以这里一般成立
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
}
// @Resource(name = "beanService1")指定name,会通过name来解析出实例
// resolveBeanByName内部通过getBean获取实例
else {
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
// 默认不成立
else {
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
// DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory
// 默认条件成立
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
for (String autowiredBe以上是关于初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource的主要内容,如果未能解决你的问题,请参考以下文章
初识Spring源码 -- applyMergedBeanDefinitionPostProcessors
初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource
初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource
初识Spring源码 -- 属性填充populateBean | 静态属性注入
初识Spring源码 -- 属性填充populateBean | 静态属性注入
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段