Spring Bean生命周期

Spring Bean生命周期

1.BeanDefinition

Spring中對(duì)象皆為bean,進(jìn)而將bean的定義信息進(jìn)行抽象為BeanDefinition酌媒,將BeanDefinition作為標(biāo)準(zhǔn)進(jìn)行創(chuàng)建。一般情況下茴扁,可以通過(guò)可以通過(guò)如下的方式進(jìn)行配置:

1.1 面向資源

1.1.1 XML配置

使用BeanDefinitionReader進(jìn)行讀取資源隧魄。xml的配置一般如下所示:

<bean id="user" class="com.johar.thinkinspring.ioc.dependency.domain.User">

? ? <property name="id" value="1"/>

? ? <property name="name" value="johar"/>

</bean>

該類的解析方式如下:

public static void main(String[] args){

? ? DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

? ? XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

? ? String location = "classpath:/dependency-lookup-context.xml";

? ? int beanDefinitionCount = reader.loadBeanDefinitions(location);

? ? System.out.println("Bean定義加載的數(shù)量:" + beanDefinitionCount);

? ? lookupCollectionByType(beanFactory);

}

private static void lookupCollectionByType(BeanFactory beanFactory){

? ? if (beanFactory instanceof ListableBeanFactory){

? ? ? ? ListableBeanFactory listableBeanFactory = (ListableBeanFactory)beanFactory;

? ? ? ? Map<String, User> userMap = listableBeanFactory.getBeansOfType(User.class);

? ? ? ? System.out.println("查找所有的User集合:" + userMap);

? ? }

}

1.1.2 Properties資源配置

Properties資源使用PropertiesBeanDefinitionReader讀取資源,源碼中PropertiesBeanDefinitionReader配置實(shí)例如下:

代碼實(shí)例如下:

user.(class)=com.johar.thinkinspring.ioc.dependency.domain.User

user.id = 100

user.name = 實(shí)例

測(cè)試代碼如下:

public static void main(String[] args) {

? ? DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

? ? PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(factory);

? ? String xmlPath = "user.properties";

? ? ClassPathResource resource = new ClassPathResource(xmlPath);

? ? EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");

? ? int beanNum = reader.loadBeanDefinitions(encodedResource);

? ? System.out.printf("load bean num = " + beanNum);

? ? User user = factory.getBean(User.class);

? ? System.out.println(user);

}

有個(gè)地方需要注意一下淹冰,PropertiesBeanDefinitionReader默認(rèn)安裝ASCII讀取,但是user.properties文件使用utf-8編碼巨柒。

1.2 面向注解

public class AnnotatedBeanDefinitionParseDemo {

? ? public static void main(String[] args) {

? ? ? ? DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

? ? ? ? AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);

? ? ? ? reader.register(AnnotatedBeanDefinitionParseDemo.class);

? ? ? ? AnnotatedBeanDefinitionParseDemo demo = beanFactory.getBean(AnnotatedBeanDefinitionParseDemo.class);

? ? ? ? System.out.println(demo);

? ? }

}

1.3 面向API

BeanDefinitionRegistry

public static void main(String[] args){

? ? BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);

? ? beanDefinitionBuilder.addPropertyValue("id", 1);

? ? beanDefinitionBuilder.addPropertyValue("name", "Johar");

? ? BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();

? ? GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();

? ? genericBeanDefinition.setBeanClass(User.class);

? ? MutablePropertyValues propertyValues = new MutablePropertyValues();

? ? propertyValues.add("id", 1);

? ? propertyValues.add("name", "Johar");

? ? genericBeanDefinition.setPropertyValues(propertyValues);

}

2.Spring Bean生命周期

Spring Bean的生命周期主要看AbstractApplicationContext的refresh()方法樱拴。

@Override

public void refresh() throws BeansException, IllegalStateException {

? synchronized (this.startupShutdownMonitor) {

? ? ? // Prepare this context for refreshing.

? ? ? // 容器刷新前的準(zhǔn)備,設(shè)置上下文狀態(tài)洋满,獲取屬性晶乔,驗(yàn)證必要的屬性等

? ? ? prepareRefresh();

? ? ? // Tell the subclass to refresh the internal bean factory.

? ? ? // 獲取新的beanFactory,銷毀原有beanFactory牺勾、為每個(gè)bean生成BeanDefinition等

? ? ? ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

? ? ? // Prepare the bean factory for use in this context.

? ? ? // 配置標(biāo)準(zhǔn)的beanFactory正罢,設(shè)置ClassLoader,設(shè)置SpEL表達(dá)式解析器驻民,添加忽略注入的接口翻具,添加bean,添加bean后置處理器等

? ? ? prepareBeanFactory(beanFactory);

? ? ? try {

? ? ? ? // Allows post-processing of the bean factory in context subclasses.

? ? ? ? // 模板方法回还,此時(shí)裆泳,所有的beanDefinition已經(jīng)加載,但是還沒(méi)有實(shí)例化柠硕。

? ? ? ? // 允許在子類中對(duì)beanFactory進(jìn)行擴(kuò)展處理工禾。比如添加ware相關(guān)接口自動(dòng)裝配設(shè)置,添加后置處理器等仅叫,是子類擴(kuò)展prepareBeanFactory(beanFactory)的方

? ? ? ? postProcessBeanFactory(beanFactory);

? ? ? ? // Invoke factory processors registered as beans in the context.

? ? ? ? // 實(shí)例化并調(diào)用所有注冊(cè)的beanFactory后置處理器(實(shí)現(xiàn)接口BeanFactoryPostProcessor的bean帜篇,在beanFactory標(biāo)準(zhǔn)初始化之后執(zhí)行)

? ? ? ? invokeBeanFactoryPostProcessors(beanFactory);

? ? ? ? // Register bean processors that intercept bean creation.

? ? ? ? //

? ? ? ? registerBeanPostProcessors(beanFactory);

? ? ? ? // Initialize message source for this context.

? ? ? ? initMessageSource();

? ? ? ? // Initialize event multicaster for this context.

? ? ? ? initApplicationEventMulticaster();

? ? ? ? // Initialize other special beans in specific context subclasses.

? ? ? ? onRefresh();

? ? ? ? // Check for listener beans and register them.

? ? ? ? registerListeners();

? ? ? ? // Instantiate all remaining (non-lazy-init) singletons.

? ? ? ? finishBeanFactoryInitialization(beanFactory);

? ? ? ? // Last step: publish corresponding event.

? ? ? ? finishRefresh();

? ? ? }

? ? ? catch (BeansException ex) {

? ? ? ? if (logger.isWarnEnabled()) {

? ? ? ? ? ? logger.warn("Exception encountered during context initialization - " +

? ? ? ? ? ? ? ? ? "cancelling refresh attempt: " + ex);

? ? ? ? }

? ? ? ? // Destroy already created singletons to avoid dangling resources.

? ? ? ? destroyBeans();

? ? ? ? // Reset 'active' flag.

? ? ? ? cancelRefresh(ex);

? ? ? ? // Propagate exception to caller.

? ? ? ? throw ex;

? ? ? }

? ? ? finally {

? ? ? ? // Reset common introspection caches in Spring's core, since we

? ? ? ? // might not ever need metadata for singleton beans anymore...

? ? ? ? resetCommonCaches();

? ? ? }

? }

}

在finishBeanFactoryInitialization中實(shí)例化非lazy加載的bean。另外Spring中ApplicationContext中實(shí)際使用的DefaultListableBeanFactory

2.1 BeanDefinition注冊(cè)-registerBeanDefinition

@Override

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

? ? ? throws BeanDefinitionStoreException {

? Assert.hasText(beanName, "Bean name must not be empty");

? Assert.notNull(beanDefinition, "BeanDefinition must not be null");

? if (beanDefinition instanceof AbstractBeanDefinition) {

? ? ? try {

? ? ? ? ((AbstractBeanDefinition) beanDefinition).validate();

? ? ? }

? ? ? catch (BeanDefinitionValidationException ex) {

? ? ? ? throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

? ? ? ? ? ? ? "Validation of bean definition failed", ex);

? ? ? }

? }

? BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);

? if (existingDefinition != null) {

? ? ? if (!isAllowBeanDefinitionOverriding()) {

? ? ? ? throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);

? ? ? }

? ? ? else if (existingDefinition.getRole() < beanDefinition.getRole()) {

? ? ? ? // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE

? ? ? ? if (logger.isInfoEnabled()) {

? ? ? ? ? ? logger.info("Overriding user-defined bean definition for bean '" + beanName +

? ? ? ? ? ? ? ? ? "' with a framework-generated bean definition: replacing [" +

? ? ? ? ? ? ? ? ? existingDefinition + "] with [" + beanDefinition + "]");

? ? ? ? }

? ? ? }

? ? ? else if (!beanDefinition.equals(existingDefinition)) {

? ? ? ? if (logger.isDebugEnabled()) {

? ? ? ? ? ? logger.debug("Overriding bean definition for bean '" + beanName +

? ? ? ? ? ? ? ? ? "' with a different definition: replacing [" + existingDefinition +

? ? ? ? ? ? ? ? ? "] with [" + beanDefinition + "]");

? ? ? ? }

? ? ? }

? ? ? else {

? ? ? ? if (logger.isTraceEnabled()) {

? ? ? ? ? ? logger.trace("Overriding bean definition for bean '" + beanName +

? ? ? ? ? ? ? ? ? "' with an equivalent definition: replacing [" + existingDefinition +

? ? ? ? ? ? ? ? ? "] with [" + beanDefinition + "]");

? ? ? ? }

? ? ? }

? ? ? this.beanDefinitionMap.put(beanName, beanDefinition);

? }

? else {

? ? ? if (hasBeanCreationStarted()) {

? ? ? ? // Cannot modify startup-time collection elements anymore (for stable iteration)

? ? ? ? synchronized (this.beanDefinitionMap) {

? ? ? ? ? ? this.beanDefinitionMap.put(beanName, beanDefinition);

? ? ? ? ? ? List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);

? ? ? ? ? ? updatedDefinitions.addAll(this.beanDefinitionNames);

? ? ? ? ? ? updatedDefinitions.add(beanName);

? ? ? ? ? ? this.beanDefinitionNames = updatedDefinitions;

? ? ? ? ? ? removeManualSingletonName(beanName);

? ? ? ? }

? ? ? }

? ? ? else {

? ? ? ? // Still in startup registration phase

? ? ? ? this.beanDefinitionMap.put(beanName, beanDefinition);

? ? ? ? this.beanDefinitionNames.add(beanName);

? ? ? ? removeManualSingletonName(beanName);

? ? ? }

? ? ? this.frozenBeanDefinitionNames = null;

? }

? if (existingDefinition != null || containsSingleton(beanName)) {

? ? ? resetBeanDefinition(beanName);

? }

? else if (isConfigurationFrozen()) {

? ? ? clearByTypeCache();

? }

}

2.2 BeanDefinition合并-getMergedBeanDefinition

父子BeanDefinition合并诫咱,先查找父BeanFactory笙隙,最后查找本地。

@Override

public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {

? String beanName = transformedBeanName(name);

? // Efficiently check whether bean definition exists in this factory.

? if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {

? ? ? return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);

? }

? // Resolve merged bean definition locally.

? return getMergedLocalBeanDefinition(beanName);

}

2.3 Bean實(shí)例化前階段-resolveBeforeInstantition

主要是執(zhí)行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation坎缭,若有返回竟痰,直接退出签钩。

@Nullable

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {

? Object bean = null;

? if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {

? ? ? // Make sure bean class is actually resolved at this point.

? ? ? if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

? ? ? ? Class<?> targetType = determineTargetType(beanName, mbd);

? ? ? ? if (targetType != null) {

? ? ? ? ? ? bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

? ? ? ? ? ? if (bean != null) {

? ? ? ? ? ? ? bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

? ? ? ? ? ? }

? ? ? ? }

? ? ? }

? ? ? mbd.beforeInstantiationResolved = (bean != null);

? }

? return bean;

}

try {

? // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

? Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

? if (bean != null) {

? ? ? return bean;

? }

}

catch (Throwable ex) {

? throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,

? ? ? ? "BeanPostProcessor before instantiation of bean failed", ex);

}

2.4 Bean 實(shí)例化階段 - createBeanInstance

使用instantiationstrategy創(chuàng)建bean實(shí)例,instantiationstrategy包括:factory method, constructor autowiring, or simple instantiation(CglibSubclassingInstantiationStrategy)

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

? // Make sure bean class is actually resolved at this point.

? Class<?> beanClass = resolveBeanClass(mbd, beanName);

? if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {

? ? ? throw new BeanCreationException(mbd.getResourceDescription(), beanName,

? ? ? ? ? ? "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());

? }

? Supplier<?> instanceSupplier = mbd.getInstanceSupplier();

? if (instanceSupplier != null) {

? ? ? return obtainFromSupplier(instanceSupplier, beanName);

? }

? if (mbd.getFactoryMethodName() != null) {

? ? ? return instantiateUsingFactoryMethod(beanName, mbd, args);

? }

? // Shortcut when re-creating the same bean...

? boolean resolved = false;

? boolean autowireNecessary = false;

? if (args == null) {

? ? ? synchronized (mbd.constructorArgumentLock) {

? ? ? ? if (mbd.resolvedConstructorOrFactoryMethod != null) {

? ? ? ? ? ? resolved = true;

? ? ? ? ? ? autowireNecessary = mbd.constructorArgumentsResolved;

? ? ? ? }

? ? ? }

? }

? if (resolved) {

? ? ? if (autowireNecessary) {

? ? ? ? return autowireConstructor(beanName, mbd, null, null);

? ? ? }

? ? ? else {

? ? ? ? return instantiateBean(beanName, mbd);

? ? ? }

? }

? // Candidate constructors for autowiring?

? Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

? if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||

? ? ? ? mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

? ? ? return autowireConstructor(beanName, mbd, ctors, args);

? }

? // Preferred constructors for default construction?

? ctors = mbd.getPreferredConstructors();

? if (ctors != null) {

? ? ? return autowireConstructor(beanName, mbd, ctors, null);

? }

? // No special handling: simply use no-arg constructor.

? return instantiateBean(beanName, mbd);

}

2.5 Bean 實(shí)例化后階段 - populateBean

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

? if (bw == null) {

? ? ? if (mbd.hasPropertyValues()) {

? ? ? ? throw new BeanCreationException(

? ? ? ? ? ? ? mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");

? ? ? }

? ? ? else {

? ? ? ? // Skip property population phase for null instance.

? ? ? ? return;

? ? ? }

? }

? // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the

? // state of the bean before properties are set. This can be used, for example,

? // to support styles of field injection.

? if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

? ? ? for (BeanPostProcessor bp : getBeanPostProcessors()) {

? ? ? ? if (bp instanceof InstantiationAwareBeanPostProcessor) {

? ? ? ? ? ? InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

? ? ? ? ? ? if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

? ? ? ? ? ? ? return;

? ? ? ? ? ? }

? ? ? ? }

? ? ? }

? }

? PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

? int resolvedAutowireMode = mbd.getResolvedAutowireMode();

? if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {

? ? ? MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

? ? ? // Add property values based on autowire by name if applicable.

? ? ? if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {

? ? ? ? autowireByName(beanName, mbd, bw, newPvs);

? ? ? }

? ? ? // Add property values based on autowire by type if applicable.

? ? ? if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {

? ? ? ? autowireByType(beanName, mbd, bw, newPvs);

? ? ? }

? ? ? pvs = newPvs;

? }

? boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

? boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

? PropertyDescriptor[] filteredPds = null;

? if (hasInstAwareBpps) {

? ? ? if (pvs == null) {

? ? ? ? pvs = mbd.getPropertyValues();

? ? ? }

? ? ? for (BeanPostProcessor bp : getBeanPostProcessors()) {

? ? ? ? if (bp instanceof InstantiationAwareBeanPostProcessor) {

? ? ? ? ? ? InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

? ? ? ? ? ? PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

? ? ? ? ? ? if (pvsToUse == null) {

? ? ? ? ? ? ? if (filteredPds == null) {

? ? ? ? ? ? ? ? ? filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

? ? ? ? ? ? ? }

? ? ? ? ? ? ? pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

? ? ? ? ? ? ? if (pvsToUse == null) {

? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? pvs = pvsToUse;

? ? ? ? }

? ? ? }

? }

? if (needsDepCheck) {

? ? ? if (filteredPds == null) {

? ? ? ? filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

? ? ? }

? ? ? checkDependencies(beanName, mbd, filteredPds, pvs);

? }

? if (pvs != null) {

? ? ? applyPropertyValues(beanName, mbd, bw, pvs);

? }

}

2.6 Bean 屬性賦值前階段 - populateBean

Bean屬性值元信息PropertyValues

Spring 5.1及以上:InstantiationAwareBeanPostProcessor#postProcessProperties

Spring 1.2-5.0 InstantiationAwareBeanPostProcessor#postProcessPropertyValues

2.7 Bean 屬性賦值階段 - populateBean

AbstractAutowireCapableBeanFactory#applyPropertyValues

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {

? if (pvs.isEmpty()) {

? ? ? return;

? }

? if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {

? ? ? ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());

? }

? MutablePropertyValues mpvs = null;

? List<PropertyValue> original;

? if (pvs instanceof MutablePropertyValues) {

? ? ? mpvs = (MutablePropertyValues) pvs;

? ? ? if (mpvs.isConverted()) {

? ? ? ? // Shortcut: use the pre-converted values as-is.

? ? ? ? try {

? ? ? ? ? ? bw.setPropertyValues(mpvs);

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? catch (BeansException ex) {

? ? ? ? ? ? throw new BeanCreationException(

? ? ? ? ? ? ? ? ? mbd.getResourceDescription(), beanName, "Error setting property values", ex);

? ? ? ? }

? ? ? }

? ? ? original = mpvs.getPropertyValueList();

? }

? else {

? ? ? original = Arrays.asList(pvs.getPropertyValues());

? }

? TypeConverter converter = getCustomTypeConverter();

? if (converter == null) {

? ? ? converter = bw;

? }

? BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

? // Create a deep copy, resolving any references for values.

? List<PropertyValue> deepCopy = new ArrayList<>(original.size());

? boolean resolveNecessary = false;

? for (PropertyValue pv : original) {

? ? ? if (pv.isConverted()) {

? ? ? ? deepCopy.add(pv);

? ? ? }

? ? ? else {

? ? ? ? String propertyName = pv.getName();

? ? ? ? Object originalValue = pv.getValue();

? ? ? ? if (originalValue == AutowiredPropertyMarker.INSTANCE) {

? ? ? ? ? ? Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();

? ? ? ? ? ? if (writeMethod == null) {

? ? ? ? ? ? ? throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);

? ? ? ? ? ? }

? ? ? ? ? ? originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);

? ? ? ? }

? ? ? ? Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

? ? ? ? Object convertedValue = resolvedValue;

? ? ? ? boolean convertible = bw.isWritableProperty(propertyName) &&

? ? ? ? ? ? ? !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);

? ? ? ? if (convertible) {

? ? ? ? ? ? convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);

? ? ? ? }

? ? ? ? // Possibly store converted value in merged bean definition,

? ? ? ? // in order to avoid re-conversion for every created bean instance.

? ? ? ? if (resolvedValue == originalValue) {

? ? ? ? ? ? if (convertible) {

? ? ? ? ? ? ? pv.setConvertedValue(convertedValue);

? ? ? ? ? ? }

? ? ? ? ? ? deepCopy.add(pv);

? ? ? ? }

? ? ? ? else if (convertible && originalValue instanceof TypedStringValue &&

? ? ? ? ? ? ? !((TypedStringValue) originalValue).isDynamic() &&

? ? ? ? ? ? ? !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {

? ? ? ? ? ? pv.setConvertedValue(convertedValue);

? ? ? ? ? ? deepCopy.add(pv);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? resolveNecessary = true;

? ? ? ? ? ? deepCopy.add(new PropertyValue(pv, convertedValue));

? ? ? ? }

? ? ? }

? }

? if (mpvs != null && !resolveNecessary) {

? ? ? mpvs.setConverted();

? }

? // Set our (possibly massaged) deep copy.

? try {

? ? ? bw.setPropertyValues(new MutablePropertyValues(deepCopy));

? }

? catch (BeansException ex) {

? ? ? throw new BeanCreationException(

? ? ? ? ? ? mbd.getResourceDescription(), beanName, "Error setting property values", ex);

? }

}

2.8 Bean Aware 接口回調(diào)階段 - initializeBean

AbstractAutowireCapableBeanFactory#invokeAwareMethods中依次BeanNameAware,BeanClassLoaderAware,BeanFactoryAware

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) {

? ? ? ? ClassLoader bcl = getBeanClassLoader();

? ? ? ? if (bcl != null) {

? ? ? ? ? ? ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);

? ? ? ? }

? ? ? }

? ? ? if (bean instanceof BeanFactoryAware) {

? ? ? ? ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

? ? ? }

? }

}

ApplicationContextAwareProcessor#postProcessorBeforeInitialization依次調(diào)用了EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware

@Override

@Nullable

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

? if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||

? ? ? ? bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||

? ? ? ? bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){

? ? ? return bean;

? }

? AccessControlContext acc = null;

? if (System.getSecurityManager() != null) {

? ? ? acc = this.applicationContext.getBeanFactory().getAccessControlContext();

? }

? if (acc != null) {

? ? ? AccessController.doPrivileged((PrivilegedAction<Object>) () -> {

? ? ? ? invokeAwareInterfaces(bean);

? ? ? ? return null;

? ? ? }, acc);

? }

? else {

? ? ? invokeAwareInterfaces(bean);

? }

? return bean;

}

2.9 Bean 初始化前階段 - initializeBean

BeanPostProcessor#postProcessBeforeInitialization

@Override

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

? ? ? throws BeansException {

? Object result = existingBean;

? for (BeanPostProcessor processor : getBeanPostProcessors()) {

? ? ? Object current = processor.postProcessBeforeInitialization(result, beanName);

? ? ? if (current == null) {

? ? ? ? return result;

? ? ? }

? ? ? result = current;

? }

? return result;

}

2.10 Bean 初始化階段 - initializeBean

@PostConstruct 標(biāo)注方法

必須加上CommonAnnotationBeanPostProcessor坏快,在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

? LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());

? try {

? ? ? metadata.invokeInitMethods(bean, beanName);

? }

? catch (InvocationTargetException ex) {

? ? ? throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());

? }

? catch (Throwable ex) {

? ? ? throw new BeanCreationException(beanName, "Failed to invoke init method", ex);

? }

? re

實(shí)現(xiàn) InitializingBean 接口的 afterPropertiesSet() 方法

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)

? ? ? throws Throwable {

? boolean isInitializingBean = (bean instanceof InitializingBean);

? 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<Object>) () -> {

? ? ? ? ? ? ? ((InitializingBean) bean).afterPropertiesSet();

? ? ? ? ? ? ? return null;

? ? ? ? ? ? }, getAccessControlContext());

? ? ? ? }

? ? ? ? catch (PrivilegedActionException pae) {

? ? ? ? ? ? throw pae.getException();

? ? ? ? }

? ? ? }

? ? ? else {

? ? ? ? ((InitializingBean) bean).afterPropertiesSet();

? ? ? }

? }

? if (mbd != null && bean.getClass() != NullBean.class) {

? ? ? String initMethodName = mbd.getInitMethodName();

? ? ? if (StringUtils.hasLength(initMethodName) &&

? ? ? ? ? ? !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&

? ? ? ? ? ? !mbd.isExternallyManagedInitMethod(initMethodName)) {

? ? ? ? invokeCustomInitMethod(beanName, bean, mbd);

? ? ? }

? }

}

自定義初始化方法

protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)

? ? ? throws Throwable {

? String initMethodName = mbd.getInitMethodName();

? Assert.state(initMethodName != null, "No init method set");

? Method initMethod = (mbd.isNonPublicAccessAllowed() ?

? ? ? ? BeanUtils.findMethod(bean.getClass(), initMethodName) :

? ? ? ? ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

? if (initMethod == null) {

? ? ? if (mbd.isEnforceInitMethod()) {

? ? ? ? throw new BeanDefinitionValidationException("Could not find an init method named '" +

? ? ? ? ? ? ? initMethodName + "' on bean with name '" + beanName + "'");

? ? ? }

? ? ? else {

? ? ? ? if (logger.isTraceEnabled()) {

? ? ? ? ? ? logger.trace("No default init method named '" + initMethodName +

? ? ? ? ? ? ? ? ? "' found on bean with name '" + beanName + "'");

? ? ? ? }

? ? ? ? // Ignore non-existent default lifecycle methods.

? ? ? ? return;

? ? ? }

? }

? if (logger.isTraceEnabled()) {

? ? ? logger.trace("Invoking init method? '" + initMethodName + "' on bean with name '" + beanName + "'");

? }

? Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

? if (System.getSecurityManager() != null) {

? ? ? AccessController.doPrivileged((PrivilegedAction<Object>) () -> {

? ? ? ? ReflectionUtils.makeAccessible(methodToInvoke);

? ? ? ? return null;

? ? ? });

? ? ? try {

? ? ? ? AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->

? ? ? ? ? ? ? methodToInvoke.invoke(bean), getAccessControlContext());

? ? ? }

? ? ? catch (PrivilegedActionException pae) {

? ? ? ? InvocationTargetException ex = (InvocationTargetException) pae.getException();

? ? ? ? throw ex.getTargetException();

? ? ? }

? }

? else {

? ? ? try {

? ? ? ? ReflectionUtils.makeAccessible(methodToInvoke);

? ? ? ? methodToInvoke.invoke(bean);

? ? ? }

? ? ? catch (InvocationTargetException ex) {

? ? ? ? throw ex.getTargetException();

? ? ? }

? }

}

2.11 Bean 初始化后階段 - initializeBean

BeanPostProcessor#postProcessAfterInitialization

@Override

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;

}

2.12 Bean 初始化完成階段 - preInstantiateSingletons

SmartInitializingSingleton#afterSingletonsInstantiated

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

? // Initialize conversion service for this context.

? if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&

? ? ? ? beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {

? ? ? beanFactory.setConversionService(

? ? ? ? ? ? beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));

? }

? // Register a default embedded value resolver if no bean post-processor

? // (such as a PropertyPlaceholderConfigurer bean) registered any before:

? // at this point, primarily for resolution in annotation attribute values.

? if (!beanFactory.hasEmbeddedValueResolver()) {

? ? ? beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));

? }

? // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.

? String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);

? for (String weaverAwareName : weaverAwareNames) {

? ? ? getBean(weaverAwareName);

? }

? // Stop using the temporary ClassLoader for type matching.

? beanFactory.setTempClassLoader(null);

? // Allow for caching all bean definition metadata, not expecting further changes.

? beanFactory.freezeConfiguration();

? // Instantiate all remaining (non-lazy-init) singletons.

? beanFactory.preInstantiateSingletons();

}

2.13 Bean 銷毀前階段 - destroyBean

DestructionAwareBeanPostProcessor#postProcessBeforeDestruction

在DisposableBeanAdapter#destroy中調(diào)用

public void destroy() {

? if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {

? ? ? for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {

? ? ? ? processor.postProcessBeforeDestruction(this.bean, this.beanName);

? ? ? }

? }

? if (this.invokeDisposableBean) {

? ? ? if (logger.isTraceEnabled()) {

? ? ? ? logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");

? ? ? }

? ? ? try {

? ? ? ? if (System.getSecurityManager() != null) {

? ? ? ? ? ? AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {

? ? ? ? ? ? ? ((DisposableBean) this.bean).destroy();

? ? ? ? ? ? ? return null;

? ? ? ? ? ? }, this.acc);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? ((DisposableBean) this.bean).destroy();

? ? ? ? }

? ? ? }

? ? ? catch (Throwable ex) {

? ? ? ? String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";

? ? ? ? if (logger.isDebugEnabled()) {

? ? ? ? ? ? logger.warn(msg, ex);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? logger.warn(msg + ": " + ex);

? ? ? ? }

? ? ? }

? }

? if (this.destroyMethod != null) {

? ? ? invokeCustomDestroyMethod(this.destroyMethod);

? }

? else if (this.destroyMethodName != null) {

? ? ? Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);

? ? ? if (methodToInvoke != null) {

? ? ? ? invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));

? ? ? }

? }

}

2.14 Bean 銷毀階段 - destroyBean

依次調(diào)用:@PreDestroy 標(biāo)注方法铅檩、實(shí)現(xiàn) DisposableBean 接口的 destroy() 方法、自定義銷毀方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末莽鸿,一起剝皮案震驚了整個(gè)濱河市昧旨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌祥得,老刑警劉巖兔沃,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異级及,居然都是意外死亡乒疏,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門饮焦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怕吴,“玉大人,你說(shuō)我怎么就攤上這事县踢∽粒” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵硼啤,是天一觀的道長(zhǎng)暇咆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丙曙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任其骄,我火速辦了婚禮亏镰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拯爽。我一直安慰自己索抓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布毯炮。 她就那樣靜靜地躺著逼肯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桃煎。 梳的紋絲不亂的頭發(fā)上篮幢,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音为迈,去河邊找鬼三椿。 笑死缺菌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搜锰。 我是一名探鬼主播伴郁,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蛋叼!你這毒婦竟也來(lái)了焊傅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狈涮,失蹤者是張志新(化名)和其女友劉穎狐胎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體薯嗤,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顽爹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骆姐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镜粤。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖玻褪,靈堂內(nèi)的尸體忽然破棺而出肉渴,到底是詐尸還是另有隱情,我是刑警寧澤带射,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布同规,位于F島的核電站,受9級(jí)特大地震影響窟社,放射性物質(zhì)發(fā)生泄漏券勺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一灿里、第九天 我趴在偏房一處隱蔽的房頂上張望关炼。 院中可真熱鬧,春花似錦匣吊、人聲如沸儒拂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)社痛。三九已至,卻和暖如春命雀,著一層夾襖步出監(jiān)牢的瞬間蒜哀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工咏雌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凡怎,地道東北人校焦。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像统倒,于是被迫代替她去往敵國(guó)和親寨典。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344