Spring源码解读IOC

前两篇文章介绍了Spring解析Xml/Annotion标签和通过解读Spring源码得到Spring的一些拓展,地址分别为:
http://blog.csdn.net/lgq2626/article/details/78722978
http://blog.csdn.net/lgq2626/article/details/78729368
今天,继续跟着Spring的源码走,在分析源码之前,先介绍一个内省机制,内省机制和反射机制是有区别的,反射机制可以动态获取一个bean,动态执行bean里面的方法,但是内省机制就是动态操作对象属性,测试Demo附上:

public class Student {
    private String name;
    private TestService testService;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public static void main(String[] args) throws Exception {
        Student s = new Student();
        PropertyDescriptor pd = new PropertyDescriptor("name",s.getClass());
        Method m =  pd.getWriteMethod();//获取set方法
        m.setAccessible(true);
        m.invoke(s, "你好");
        Method mr =  pd.getReadMethod();//获取get方法
        mr.setAccessible(true);
        Object obj =  mr.invoke(s, null);
        System.out.println(obj.toString());
    }
内省机制的包在java.beans.*下面

下面接着分析Spring 源码,上篇文章分析到AbstractApplicationContext类的refresh里面一些拓展,这次分析
refresh()方法下的finishBeanFactoryInitialization(beanFactory);方法,也就是SpringIOC的过程,点开方法,一直找到beanFactory.preInstantiateSingletons();方法的调用,进去后发现:

List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

这个beanDefinitionNames在第一篇文章的时候分析过,xml和annotation解析的时候会把beanName放到beanDefinitionNames这个list中来,下面就是对这个list的遍历,我们直接看else里面的getBean方法,找到doGetBean这个方法,这里有判断这个属性是否有单例的,是否是多例的,我们主要分析单例里面的createBean(beanName, mbd, args);方法,点进去createBean找到doCreateBean方法,这里看到有一个BeanWrapper对象,这个BeanWrapper对象就是对bean做了一些包装,并且这个BeanWrapper实现了PropertyAccessor的子接口,所以BeanWrapper可以set、get 被封装对象的属性值

    instanceWrapper = createBeanInstance(beanName, mbd, args);//对bean进行反射创建

上述一行代码就是对bean进行创建,通过反射的方式,代码比较简答这里不做分析,下面看populateBean(beanName, mbd, instanceWrapper);行代码,点进去

PropertyValues pvs = mbd.getPropertyValues();//获取该对象的属性

然后一直跟到

if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

会进入这个if,我们看pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);方法,有好多实现了这个方法的类,重点分析AutowiredAnnotationBeanPostProcessor类的postProcessPropertyValues方法,一直跟进到AutowiredAnnotationBeanPostProcessor类的inject方法,我们跟进到value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);方法,
重点分析

if (result == null) {
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }

重点分析doResolveDependency方法,我们进去

Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

这一行代码,这是对数组、集合、map的一些封装取值,这里的话我们重点分析@autowire的现在对象,所以这个方法返回的是一个null,我们进入到这个方法里,

findAutowireCandidates(
            String beanName, Class<?> requiredType, DependencyDescriptor descriptor)

这段代码有对

for (String candidate : candidateNames) {
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }

这个addCandidateEntry()方法有对doGetBean方法的二次调用,获取到一个单例的bean对象,返回去,这次进去的话就不走else,,直接走的if,
就是这一块代码

if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

然后对这个key(属性名字)和value(属性value)进行一个map封装,然后执行到

String autowiredBeanName;
            Object instanceCandidate;
else {
                // We have exactly one match.
                Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
                autowiredBeanName = entry.getKey();
                instanceCandidate = entry.getValue();
            }
            return (instanceCandidate instanceof Class ?
                    descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);

返回这个属性的value,到现在为止,仅仅分析的是AutoWireFieldElement类中的inject方法中的

try {
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                }

这句话,这里得到一个属性的值,
然后

if (value != null) {
                ReflectionUtils.makeAccessible(field);//设置方法可操作
                field.set(bean, value);//内省机制set值
            }

最后走到这个if方法里,通过内省机制进行设置值,到目前为止,整个@autowire下面的属性就不为空了,有值了。
下面我们分析配置文件的属性注入,

<bean class="com.study.www.vo.Student" id="student">
        <property name="name" value="ceshi"></property>
    </bean>  

这种name是怎么注入进来的?
还是跟着populateBean()方法看,找到

applyPropertyValues(beanName, mbd, bw, pvs);

重点分析这一行代码,首先会拿到

<property name="name" value="ceshi"></property>

这种配置,封装在List original;对象里面,
我们跟到

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

这一行代码,这个方法是对参数类型的一个匹配,以下的这个代码块就是对string取值的一个封装,得到了value值,返回给resolvedValue 变量

// Convert value to target type here.
            TypedStringValue typedStringValue = (TypedStringValue) value;
            Object valueObject = evaluate(typedStringValue);
            try {
                Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
                if (resolvedTargetType != null) {
                    return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
                }
                else {
                    return valueObject;
                }
            }
            catch (Throwable ex) {
                // Improve the message by showing the context.
                throw new BeanCreationException(
                        this.beanDefinition.getResourceDescription(), this.beanName,
                        "Error converting typed String value for " + argName, ex);
            }

中间做了一系列的转变赋值,这个就不细说了,重点是,

bw.setPropertyValues(new MutablePropertyValues(deepCopy));

这个方法也是应用内省机制,给变量设置值。到这里,整个IOC的属性就全部有值了,仅仅执行的是doCreateBean方法中的populateBean(beanName, mbd, instanceWrapper);这一行代码,
接着就该注册了,注册就比较简单了,

// Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }

点进去分析之后就发现仅仅是

synchronized (this.disposableBeans) {
            this.disposableBeans.put(beanName, bean);
        }

这么一行代码,注册到了DefaultSingletonBeanRegistry对象的disposableBeans 容器中。
上面就是SpringIOC容器注入的简单分析,若有错误,希望大神帮忙指出,谢谢

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值