前两篇文章介绍了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容器注入的简单分析,若有错误,希望大神帮忙指出,谢谢