spring中bean的生命周期和作用域,Spring中bean的生命周期
目录
前言属性自动装配属性赋值前回调属性的真正赋值总结
前言
上节在谈论豆的实例化过程时,在说明实例化后阶段时只是粗略地看了一下populateBean,并未展开分析。本节接着人口豆开始分析对象赋值阶段的事情。
populateBean其实主要做了以下几件事:
豆实例化后回调,来决定是否进行属性赋值(上节分析过了)对属性进行自动装配instantiationwarebeanpostprocessor属性赋值前回调属性的真正赋值受保护的void填充bean(字符串bean名称,RootBeanDefinition mbd,@Nullable BeanWrapper bw) {//省略无关代码//1、Bean实例化后回调,来决定是否进行属性赋值如果(!mbd。is synthetic()hasinstantiationwarebeanpostprocessors()){ for(BeanPostProcessor BP : getBeanPostProcessors()){ if(instantiationwarebeanpostprocessor的BP实例){ instantiationwarebeanpostprocessor IBP=(instantiationwarebeanpostprocessor)BP;如果(!IBP。postprocessafterinstance(bw。getwrapppedinstance(),bean name)){ return;} } } }属性值PVS=(mbd。haspropertyvalues()?mbd。getpropertyvalues(): null);//2、对属性进行自动装配int resolvedAutowireMode=mbd。getresolvedautowiremode();if(resolvedAutowireMode==auto wire _ BY _ NAME resolvedAutowireMode==auto wire _ BY _ TYPE){ MutablePropertyValues new PVS=new MutablePropertyValues(PVS);//如果适用,根据按名称自动关联添加属性值.if(resolvedAutowireMode==AUTOWIRE _ BY _ NAME){ autowireByName(bean NAME,mbd,bw,new PVS);}//如果适用,根据按类型自动关联添加属性值.if(resolvedAutowireMode==AUTOWIRE _ BY _ TYPE){ autowireByType(bean name,mbd,bw,new PVS);} pvs=newPvs}布尔hasInstAwareBpps=hasinstationawarebeanpostprocessors();boolean needsDepCheck=(mbd。getdependencycheck()!=AbstractBeanDefinition .依赖_检查_无);//3、instantiationwarebeanpostprocessor属性赋值前回调属性描述符[]filtered PDS=null;if(hasInstAwareBpps){ if(PVS==null){ PVS=mbd。getpropertyvalues();} for(BeanPostProcessor BP : getBeanPostProcessors()){ if(instantiationwarebeanpostprocessor的BP实例){ instantiationwarebeanpostprocessor IBP=(instantiationwarebeanpostprocessor)BP;属性值pvsToUse=IBP。postprocessproperties(PVS,bw.getWrappedInstance(),bean名称);if(pvsToUse==null){ if(filteredPds==null){ filteredPds=filterPropertyDescriptorsForDependencyCheck(bw,mbd。允许缓存);}pvsT
oUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}//省略无关代码if (pvs != null) { //属性的赋值applyPropertyValues(beanName, mbd, bw, pvs);}}
属性自动装配
PropertyValues 对bd中属性的封装,可以理解为bd中属性键值均由其保存,其常用实现类为MutablePropertyValues,在BeanDefinition的概述及使用 有介绍其使用,可点击查看
//这里的bd是已经执行过合并BeanDefinition操作了 //如果bd存在属性 则获取 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//获取bd的自动注入模式 //注入模式有四种://1.构造函数注入 2、按照名称注入 3、按照类型注入 4、不注入(默认,依然可能会被注解驱动注入)int resolvedAutowireMode = mbd.getResolvedAutowireMode();//如果是按名称注入或类型注入时if (resolvedAutowireMode == AUTOWIRE_BY_NAME resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);//按名称注入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;}
下面我们分别来大致看下autowireByName
及autowireByType
熟悉下实现原理
autowireByName
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {//获取属性名称String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//遍历属性名称for (String propertyName : propertyNames) { //如果属性名称已在beanDefinitionMap中,说明其是bd 并已被注册待IoC容器if (containsBean(propertyName)) { //根据名称获取其bean对象Object bean = getBean(propertyName);//以键值方法赋值到pvspvs.add(propertyName, bean);// 这里是维护dependentBeanMap、dependenciesForBeanMap两个集合,// 这里不再展开 在说到LifecycleProcessor时再展开registerDependentBean(propertyName, beanName);//省略日志输出}else {//省略日志输出}}}
autowireByType
按类型注入稍显复杂些,但流程上与按名称注入类似
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {//类型转换器TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set<String> autowiredBeanNames = new LinkedHashSet<>(4);//依然是获取属性名称String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//遍历属性名称for (String propertyName : propertyNames) {try { //获取属性描述对象PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);//不对Object类型做注入,因此这里判断条件如下if (Object.class != pd.getPropertyType()) {MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);//解析依赖Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {//以键值方法赋值到pvspvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) { // 这里是维护dependentBeanMap、dependenciesForBeanMap两个集合, // 这里不再展开 在说到LifecycleProcessor时再展开registerDependentBean(autowiredBeanName, beanName);//省略日志输出}autowiredBeanNames.clear();}}catch (BeansException ex) {//省略异常信息}}
接下来我们进入到resolveDependency
,大致分析下解析依赖的主要流程
DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); //如果依赖类型是Optionalif (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);} //如果依赖类型是ObjectFactory或ObjectProviderelse if (ObjectFactory.class == descriptor.getDependencyType() ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);} //如果依赖类型是Injectelse if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) { //实际执行解析依赖的逻辑代码 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}@Nullablepublic Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {return shortcut;}//获取依赖类型Class<?> type = descriptor.getDependencyType(); //获取依赖类型的默认值,如@Value注解 可提供默认值Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value != null) { //如果默认值是String类型if (value instanceof String) { //从配置文件中解析出指定key的数据String strVal = resolveEmbeddedValue((String) value);BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);value = evaluateBeanDefinitionString(strVal, bd);} //类型转换器 用于转换类型,如配置文件中声明的是字符串类型的数字,而java中使用Integer接收,则类型转换器就派上用场了TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}//解析出类型是Stream、Map、数组、Collection等集合类型的依赖。解析的思路很类似 即去IoC容器中 查找集合类实际泛型对应的BeanObject multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}//这里主要是查找单实例Bean的,如果某个类型的Bean有多个,这里会被全部查找出来,因此使用Map接收Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate; //如果查找出的Bean有多个,if (matchingBeans.size() > 1) { //找出标注了@Primary的那个Bean名称,作为查找出的BeanautowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) !indicatesMultipleBeans(type)) { //如果没有@Primary注解标注,那么抛出NoUniqueBeanDefinitionExceptionreturn descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {return null;}}instanceCandidate = matchingBeans.get(autowiredBeanName);}else { //如果查找出的Bean只有1个 那么说明找到了。Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}if (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}if (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}result = null;}if (!ClassUtils.isAssignableValue(type, result)) {throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());}return result;}finally {ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}
可以看出resolveDependency
方法还是很强大的,无论是单一类型对象还是集合类型对象,无论是Optional类型还是延迟加载ObjectFactory类型 其均可以解析出来。
属性赋值前回调
//boolean值 判断有没有InstantiationAwareBeanPostProcessor存在 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 这是 是否依赖检查的标记 不是我们此次的重点boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;//IoC容器中如果存在InstantiationAwareBeanPostProcessorif (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}//遍历BeanPostProcessor,找到InstantiationAwareBeanPostProcessor类型for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;//postProcessProperties、postProcessPropertyValues两个方法含义类似。如果postProcessProperties未被重写 则执行postProcessPropertyValues方法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;}}}
这里针对一个小案例说明下postProcessPropertyValues
和postProcessProperties
的使用
需求:将注入的user对象中name属性由wojiushiwo修改为abc
实体对象User
@Data@ToStringpublic class User { private String name; private Integer age; public User() { } public User(String name, Integer age) { this.name = name; this.age = age; }}
public class MyInstantiationBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if(ObjectUtils.nullSafeEquals("user",beanName) && User.class.equals(bean.getClass())){ final MutablePropertyValues propertyValues; if(pvs instanceof MutablePropertyValues){ propertyValues= (MutablePropertyValues) pvs; }else{ propertyValues=new MutablePropertyValues(); } if(propertyValues.contains("name")){ propertyValues.removePropertyValue("name"); propertyValues.addPropertyValue("name","abcd"); } return propertyValues; } return null; }}
public class BeanPostProcessDemo { public static void main(String[] args) { BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class); beanDefinitionBuilder.addPropertyValue("name", "wojiushiwo"); beanDefinitionBuilder.addPropertyValue("age", 20); // 获取 AbstractBeanDefinition AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition(); // 附加属性( beanDefinition.setAttribute("name", "我是附加属性"); // 当前 BeanDefinition 来自哪里(辅助作用) beanDefinition.setSource(BeanPostProcessDemo.class); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); beanFactory.addBeanPostProcessor(new MyInstantiationBeanPostProcessor()); // 注册 User 的 BeanDefinition beanFactory.registerBeanDefinition("user", beanDefinition); User user = beanFactory.getBean("user", User.class); System.out.println(user); }}
输出结果:
User(name=abcd, age=20)
属性的真正赋值
if (pvs != null) { //将从前面步骤得到的pvs 赋值到beanWrapper中以实现属性赋值,这部分具体源码这里不展开了applyPropertyValues(beanName, mbd, bw, pvs);}
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注盛行IT的更多内容!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。