本代码来自https://www.bilibili.com/video/BV1Np4y1z7BU?p=137
spring IOC相关接口分析 BeanFactory解析BeanFactory是最基础的一个接口,他之定义了IOC容器的基本规范,但是不规定具体要生产那些产品,具体的生产步骤交给该接口的子实现类去实现。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
// 根据beanName获取IOC容器中的对象
Object getBean(String name) throws BeansException;
// 根据beanName获取IOC容器中的对象,并且强转成requiredType类型
T getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
T getBean(Class requiredType) throws BeansException;
T getBean(Class requiredType, Object... args) throws BeansException;
ObjectProvider getBeanProvider(Class requiredType);
ObjectProvider getBeanProvider(ResolvableType requiredType);
// 判断容器中是否包含指定名称的bean对象
boolean containsBean(String name);
// 判断相应beanName的bean对象是否是单例的
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
我们在使用spring的时候通常都是用ClassPathXmlApplicationContext来生成一个容器
public class Application {
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
UserController userController = (UserController) applicationContext.getBean("userController");
userController.add();
}
}
下面我们来看一下ClassPathXmlApplicationContext的具体内容
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
@Nullable
private Resource[] configResources;
// 无参构造
public ClassPathXmlApplicationContext() {
}
// 调用父类初始化
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
// 传入xml的文件目录,最后会跳转到核心方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
throws BeansException {
this(configLocations, true, parent);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
// 这是构造方法中的核心方法,其中调用了refresh,这个方法就是非延时加载
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
public ClassPathXmlApplicationContext(String path, Class> clazz) throws BeansException {
this(new String[] {path}, clazz);
}
public ClassPathXmlApplicationContext(String[] paths, Class> clazz) throws BeansException {
this(paths, clazz, null);
}
public ClassPathXmlApplicationContext(String[] paths, Class> clazz, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
@Override
@Nullable
protected Resource[] getConfigResources() {
return this.configResources;
}
}
BeanDefinition解析
spring IOC容器中使用BeanDefinition来定义Bean对象
public interface BeanDefinition extends AttributeAccessor, BeanmetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
void setScope(@Nullable String scope);
@Nullable
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable
String getDescription();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
BeanDefinitionReader解析
BeanDefinitionReader主要完成Bean的解析
public interface BeanDefinitionReader {
// 这个方法是重点方法,获取注册表
BeanDefinitionRegistry getRegistry();
@Nullable
ResourceLoader getResourceLoader();
@Nullable
ClassLoader getBeanClassLoader();
BeanNameGenerator getBeanNameGenerator();
// 加载配置文件,并解析成BeanDefinitions
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}
BeanDefinitionRegistry解析
这类接口用来封装BeanDefinition
public interface BeanDefinitionRegistry extends AliasRegistry {
// 往注册表中注册bean
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
// 从注册表中删除指定名称的bean
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 获取注册表中指定名称的bean
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 判断注册表中是否一定注册了指定名称的bean
boolean containsBeanDefinition(String beanName);
// 获取注册表中所有bean的名称
String[] getBeanDefinitionNames();
// 获取注册表中已经注册的bean数量
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
这个接口中的子实现类中最简单是SimpleBeanDefinitionRegistry
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
private final Map beanDefinitionMap = new ConcurrentHashMap<>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "'beanName' must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
this.beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
if (this.beanDefinitionMap.remove(beanName) == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
@Override
public boolean containsBeanDefinition(String beanName) {
return this.beanDefinitionMap.containsKey(beanName);
}
@Override
public String[] getBeanDefinitionNames() {
return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
}
@Override
public int getBeanDefinitionCount() {
return this.beanDefinitionMap.size();
}
@Override
public boolean isBeanNameInUse(String beanName) {
return isAlias(beanName) || containsBeanDefinition(beanName);
}
}
创建容器
我们调用ClassPathXmlApplicationContext创建容器的时候是调用refresh()方法,该方法是由AbstractXmlApplicationContext具体实现的。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
// ...
// 这个方法非常重要,主要的创建bean对象的步骤都在里面
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
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();
}
}
}
// ...
}
自制spring IOC容器
PropertyValue
我们首先需要定义一个PropertyValue类来存储bean标签中的property标签,其中有三个属性:name,ref和value,分别用来存储property标签的属性。
public class PropertyValue {
private String name;
private String ref;
private String value;
public PropertyValue() {}
public PropertyValue(String name, String ref, String value) {
this.name = name;
this.ref = ref;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "PropertyValue{" +
"name='" + name + ''' +
", ref='" + ref + ''' +
", value='" + value + ''' +
'}';
}
}
MutablePropertyValues
由于一个bean标签可以有多个子标签,因此我们需要定义一个MutablePropertyValues类来存储和管理多个PropertyValue类
public class MutablePropertyValues implements Iterator{ // 定义一个容器,用来存放PropertyValue对象 private final List propertyValueList; public MutablePropertyValues(){ this.propertyValueList = new ArrayList (); } public MutablePropertyValues(List propertyValueList) { if(propertyValueList == null){ this.propertyValueList = new ArrayList (); return; } this.propertyValueList = propertyValueList; } // 将PropertyValues的内容以数组的形式返回 public PropertyValue[] getPropertyValues(){ return propertyValueList.toArray(new PropertyValue[0]); } // 根据name属性值获取PropertyValue对象 public PropertyValue getPropertyValueByName(String name){ for(PropertyValue propertyValue : propertyValueList){ if(propertyValue.getName().equals(name)){ return propertyValue; } } //throw new RuntimeException("没有[name="+name+"]的PropertyValue对象"); return null; } // 判断集合是否为空 public boolean isEmpty(){ return propertyValueList.size()==0 ? true : false; } // 添加PropertyValue对象 public MutablePropertyValues addPropertyValue(PropertyValue pv){ // 判断传入的PropertyValue对象是否已经在容器中 // 如果是,那么直接覆盖;如果不是,那么就将pv对象添加到容器中 for(int i=0; i BeanDefinition BeanDefinition用来存储bean信息,主要包括id,class还有子标签property数据
public class BeanDefinition { private String id; private String className; private MutablePropertyValues mutablePropertyValues; public BeanDefinition(){ this.mutablePropertyValues = new MutablePropertyValues(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public MutablePropertyValues getMutablePropertyValues() { return mutablePropertyValues; } public void setMutablePropertyValues(MutablePropertyValues mutablePropertyValues) { this.mutablePropertyValues = mutablePropertyValues; } }BeanDefinitionRegistry接口BeanDefinitionRegistry接口定义注册表的相关操作,包括
注册BeanDefinition对象到注册表中
从注册表中删除指定名称的BeanDefinition对象
根据名称从注册表中获取BeanDefinition对象
判断注册表中是否包含指定名称的BeanDefinition对象
获取注册表中BeanDefinition对象的个数
获取注册表中所有的BeanDefinition的名称
public interface BeanDefinitionRegistry { // 注册BeanDefinition对象到注册表中 void registerBeanDefinitin(String beanName, BeanDefinition beanDefinition); // 从注册表中删除指定名称的BeanDefinition对象 void removeBeanDefinition(String beanName) throws Exception; // 根据名称从注册表中获取BeanDefinition对象 BeanDefinition getBeanDefinition(String beanName) throws Exception; // 判断注册表中是否包含指定名称的BeanDefinition对象 boolean containsBeanDefinition(String beanName); // 获取注册表中BeanDefinition对象的个数 int getBeanDefinitionCount(); // 获取注册表中所有的BeanDefinition的名称 String[] getBeanDefinitionNames(); }SimpleBeanDefinitionRegistrySimpleBeanDefinitionRegistry是BeanDefinitionRegistry的一个子实现类
public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry{ // 定义一个容器,用来存储BeanDefinition对象 private MapBeanDefinitionReader接口beanDefinitionMap = new HashMap (); public void registerBeanDefinitin(String beanName, BeanDefinition beanDefinition) { beanDefinitionMap.put(beanName, beanDefinition); } public void removeBeanDefinition(String beanName) throws Exception { beanDefinitionMap.remove(beanName); } public BeanDefinition getBeanDefinition(String beanName) throws Exception { return beanDefinitionMap.get(beanName); } public boolean containsBeanDefinition(String beanName) { return beanDefinitionMap.containsKey(beanName); } public int getBeanDefinitionCount() { return beanDefinitionMap.size(); } public String[] getBeanDefinitionNames() { return beanDefinitionMap.keySet().toArray(new String[0]); } } BeanDefinitionReader用来解析配置文件,并在注册表中注册bean信息,定义了两个规范
获取注册表
加载配置文件并注册bean信息
public interface BeanDefinitionReader { // 获取注册表 BeanDefinitionRegistry getRegistry(); // 加载配置文件,并注册bean信息 void loadBeanDefinitions(String configLocation) throws Exception; }XmlBeanDefinitionReaderXmlBeanDefinitionReader是BeanDefinitionReader的子实现类,使用dom4j解析xml配置文件
public class XmlBeanDefinitionReader implements BeanDefinitionReader { // 声明注册表对象 private BeanDefinitionRegistry registry; public XmlBeanDefinitionReader(){ registry = new SimpleBeanDefinitionRegistry(); } public BeanDefinitionRegistry getRegistry() { return registry; } public void loadBeanDefinitions(String configLocation) throws Exception { // 使用dom4j进行配置文件解析 SAXReader reader = new SAXReader(); // 获取类路径下的配置文件 InputStream resourceAsStream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation); document document = reader.read(resourceAsStream); // 根据document对象获取根标签对象(beans) Element rootElement = document.getRootElement(); // 获取根标签下所有的bean标签对象(bean) ListBeanFactory接口beanElements = rootElement.elements("bean"); // 遍历集合 for(Element bean : beanElements){ // 获取id属性 String id = bean.attributevalue("id"); // 获取class属性 String className = bean.attributevalue("class"); // 将id属性和class属性封装到BeanDefinition对象中 // 创建BeanDefinition BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setId(id); beanDefinition.setClassName(className); // 获取property对象 List propertyElements = bean.elements("property"); MutablePropertyValues mutablePropertyValues = new MutablePropertyValues(); for(Element property : propertyElements){ String name = property.attributevalue("name"); String ref = property.attributevalue("ref"); String value = property.attributevalue("value"); PropertyValue propertyValue = new PropertyValue(name, ref, value); mutablePropertyValues.addPropertyValue(propertyValue); } beanDefinition.setMutablePropertyValues(mutablePropertyValues); // 将BeanDefinition对象注册到注册表中 registry.registerBeanDefinitin(id, beanDefinition); } } } 在该接口中定义IOC容易的统一规范,即获取bean对象
public interface BeanFactory { Object getBean(String name) throws Exception;ApplicationContext接口T getBean(String name, Class extends T> clazz) throws Exception; } 在该接口中定义refresh()方法,该接口主要完成两个功能
加载配置文件根据注册表中的BeanDefinition对象封装的数据进行bean的创建
public interface ApplicationContext extends BeanFactory { void refresh() throws Exception; }AbstractApplicationContext该类是ApplicationContext的子实现类,可以实现非延时加载。需要在类中定义一个Map容器,用来存储bean对象声明BeanDefinitionReader类型的变量,用来进行配置文件的解析
public abstract class AbstractApplicationContext implements ApplicationContext { // xml解析器 protected BeanDefinitionReader beanDefinitionReader; // 存放bean对象的容器 protected MapClassPathXmlApplicationContextsingletonObject = new HashMap (); // 配置文件类路径的变量 protected String ConfigLocation; public void refresh() throws Exception { // 加载BeanDefinition对象 beanDefinitionReader.loadBeanDefinitions(ConfigLocation); // 初始化bean finishBeanInitialization(); } // 初始化bean private void finishBeanInitialization() throws Exception{ // 获取注册表 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry(); // 获取BeanDefinition对象 String[] beanNames = registry.getBeanDefinitionNames(); // 进行bean的初始化 for(String beanName : beanNames){ getBean(beanName); } } } 该类加载类路径下的配置文件,并进行bean对象的创建,主要完成一下功能
在构造方法中创建BeanDefinitionReader对象在构造方法中调用refresh()方法重写父接口中的getbean()方法,并实现依赖注入操作
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{ public ClassPathXmlApplicationContext(String ConfigLocation){ this.ConfigLocation = ConfigLocation; // 构建解析器对象 beanDefinitionReader = new XmlBeanDefinitionReader(); try{ refresh(); } catch (Exception e){ } } // 根据bean对象的名称获取bean对象 public Object getBean(String name) throws Exception { // 判断对象容器中是否包含指定名称的bean对象 // 如果包含直接返回;如果不含包,需要自行创建 Object obj = singletonObject.get(name); if(obj != null){ return obj; } // 获取BeanDefinition对象 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry(); BeanDefinition beanDefinition = registry.getBeanDefinition(name); // 获取bean信息中的className String className = beanDefinition.getClassName(); // 通过反射创建对象 Class> clazz = Class.forName(className); Object beanObj = clazz.newInstance(); // 依赖注入 MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); for(PropertyValue propertyValue : propertyValues){ String propertyName = propertyValue.getName(); String value = propertyValue.getValue(); String ref = propertyValue.getRef(); if(ref!=null && !"".equals(ref)){ // 获取依赖的bean对象 Object bean = getBean(ref); // 拼接方法名 String methodName = StringUtils.getSetMethodByFieldName(propertyName); // 获取所有的方法对象 Method[] methods = clazz.getMethods(); for(Method method : methods){ if(method.getName().equals(methodName)){ // 执行该方法 method.invoke(beanObj, bean); } } } if(value!=null && !"".equals(value)){ // 拼接方法名 String methodName = StringUtils.getSetMethodByFieldName(propertyName); // 获取method对象 Method method = clazz.getMethod(methodName); method.invoke(beanObj, value); } } // 在返回beanObj对象前将该对象存储到map容器中 singletonObject.put(name, beanObj); return beanObj; } publicT getBean(String name, Class extends T> clazz) throws Exception { Object bean = getBean(name); if(bean == null){ return null; } return clazz.cast(bean); } } 上面的代码用到了StringUtils工具类
public class StringUtils { private StringUtils(){} public static String getSetMethodByFieldName(String FieldName){ String methodName = "set" + FieldName.substring(0,1).toUpperCase() + FieldName.substring(1); return methodName; } }项目的完整架构如下
测试代码我们编写一个简单的项目进行测试
项目分为controller层,service层和dao层,整体架构如下
public interface UserDao { // 添加方法 public void add(); }public class UserDaoImpl implements UserDao { public UserDaoImpl(){ System.out.println("UserDaoImpl init ..."); } public void add() { System.out.println("UserDao add ..."); } }public interface UserService { public void add(); }public class UserServiceImpl implements UserService { UserDao userDao; public UserServiceImpl(){ System.out.println("UserServiceImpl init ..."); } public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add() { System.out.println("UserService add ..."); userDao.add(); } }public class UserController { UserService userService; public UserController(){ System.out.println("UserController init ..."); } public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } public void add(){ System.out.println("UserController add ..."); userService.add(); } }最后编写一个测试类Application进行测试
public class Application { @Test public void test() throws Exception{ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml"); UserController userController = (UserController) applicationContext.getBean("userController"); userController.add(); } }测试结果如下所示
总结
该项目看起来十分复杂,但是将其简化后,调理还是较为清晰的。
首先,总体上可以分成以下几个部分
用来封装Bean标签的BeanDefinition,该对象里面有MutablePropertyValues对象,MutablePropertyValues又是由PropertyValue组成用来存放BeanDefinition的注册表接口BeanDefinitionRegistry,该接口的子实现类为SimpleBeanDefinitionRegistry用来进行配置文件解析的BeanDefinitionReader接口,该接口中包含有一个BeanDefinitionRegistry属性,其子实现类XmlBeanDefinitionReader实现了loadBeanDefinitions()方法,该方法解析配置文件,并且将标签的内容封装成BeanDefinition对象注册到注册表中最后就是我们进行非延时加载的容器ApplicationContext,最后我们使用的是ClassPathXmlApplicationContext,这一系列的继承实现关系较为复杂,可以用下面一张图表示。
上图就是容器对象的继承实现关系,其中有几个点是非常重要的。AbstractApplicationContext这个类中定义了xml解析器BeanDefinitionReader,该解析器的子实现类XmlBeanDefinitionReader中有注册表BeanDefinitionRegistry,进行实例化的时候,用的是注册表的子实现类SimpleBeanDefinitionRegistry。
AbstractApplicationContext中还有存放bean对象的容器Map
singletonObject,实例化后的bean对象都存放到这里。 refresh()完成bean对象的创建,其步骤为:1)加载所有的BeanDefinition对象。2)获取BeanDefinition对象,生成相应的bean对象并且注册到注册表中。
public abstract class AbstractApplicationContext implements ApplicationContext { // xml解析器 protected BeanDefinitionReader beanDefinitionReader; // 存放bean对象的容器 protected MapsingletonObject = new HashMap (); // 配置文件类路径的变量 protected String ConfigLocation; public void refresh() throws Exception { // 加载BeanDefinition对象 beanDefinitionReader.loadBeanDefinitions(ConfigLocation); // 初始化bean finishBeanInitialization(); } // 初始化bean private void finishBeanInitialization() throws Exception{ // 获取注册表 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry(); // 获取BeanDefinition对象 String[] beanNames = registry.getBeanDefinitionNames(); // 进行bean的初始化 for(String beanName : beanNames){ getBean(beanName); } } } refresh()方法中用到了finishBeanInitialization()方法,其中有一个getBean()方法,该方法的具体实现是在ClassPathXmlApplicationContext中完成的。
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{ //... // 根据bean对象的名称获取bean对象 public Object getBean(String name) throws Exception { // 判断对象容器中是否包含指定名称的bean对象 // 如果包含直接返回;如果不含包,需要自行创建 Object obj = singletonObject.get(name); if(obj != null){ return obj; } // 获取BeanDefinition对象 BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry(); BeanDefinition beanDefinition = registry.getBeanDefinition(name); // 获取bean信息中的className String className = beanDefinition.getClassName(); // 通过反射创建对象 Class> clazz = Class.forName(className); Object beanObj = clazz.newInstance(); // 依赖注入 MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); for(PropertyValue propertyValue : propertyValues){ String propertyName = propertyValue.getName(); String value = propertyValue.getValue(); String ref = propertyValue.getRef(); if(ref!=null && !"".equals(ref)){ // 获取依赖的bean对象 Object bean = getBean(ref); // 拼接方法名 String methodName = StringUtils.getSetMethodByFieldName(propertyName); // 获取所有的方法对象 Method[] methods = clazz.getMethods(); for(Method method : methods){ if(method.getName().equals(methodName)){ // 执行该方法 method.invoke(beanObj, bean); } } } if(value!=null && !"".equals(value)){ // 拼接方法名 String methodName = StringUtils.getSetMethodByFieldName(propertyName); // 获取method对象 Method method = clazz.getMethod(methodName); method.invoke(beanObj, value); } } // 在返回beanObj对象前将该对象存储到map容器中 singletonObject.put(name, beanObj); return beanObj; } publicT getBean(String name, Class extends T> clazz) throws Exception { Object bean = getBean(name); if(bean == null){ return null; } return clazz.cast(bean); } } 以上代码已经非常复杂了,但是相对于spring源码来说还是小巫见大巫。可见,读源码还是一件非常困难的工作,想要写出spring这种级别的代码是需要长时间的学习和积累的。



