Spring探秘–开发自己的Spring框架之IOC
Spring作为JAVA最著名的框架之一很多人一定都很好奇Spring是怎么实现,因此通过这篇文章会介绍如何我是怎么自己实现Spring里的IOC功能的,相关代码请见下面的Git地址:
首先上Git:
https://github.com/qmhu/myspring
如果觉得可以求加星哦!!!
测试代码
获取bean
AnnotationApplicationContext applicationContext = new AnnotationApplicationContext("content-test.xml");
Teacher teacher = (Teacher) applicationContext.getBean("teacher");
System.out.println(teacher.toString());
在XML里配置Bean
<bean id="teacher" class="my.bean.Teacher">
<property id="id" value="123"/>
<property id="name" value="xiaowang"/>
</bean>
<bean id="student" class="my.bean.Student">
<property id="id" value="333"/>
<property id="name" value="student name"/>
</bean>
<component-scan base-package="my" />
用annotation配置Bean和field(field spring里没有。。。)
@Service
public class Country {
@Field(value = "123")
private int id;
@Field(value = "countryname")
private String name;
可以看到基本跟使用spring是差不多的。
基本概念
IOC:依赖注入,我的理解是通过配置来帮助程序管理依赖,有点data driven的意思。
Container:Spring里的container是指spring创建出来的bean的lifecycle都是被container统一配置和管理的。
Bean:Spring创建出来的对象。
BeanDefinition:Spring里定义一个对象的属性。
BeanProperty:Bean的property。
ApplicationContext:Spring暴露给用户的类。
BeanFactory:负责创建Bean的factory
BeanDefinitionLoader:负责load BeanDefinition的类
AutowireBeanFactory:负责自动inject成员变量的类
加载BeanDefinition
通过BeanDefinitionXMLLoader加载BeanDefinition再注册到BeanFactory里
beanDefinationLoader = new BeanDefinationXMLLoader();
beanDefinationLoader.loadBeanDefinations(configName);
for (BeanDefinition beanDefinition : beanDefinationLoader.getBeanDefinitions()){
beanFactory.registerBeanDefinition(beanDefinition);
}
GetBean
getBean会首先从beanCache里看是否已有构建好的bean,如果没有则通过BeanDefinition创建出Bean对象,放入beanCache再返回。
public Object getBean(String name) {
Object bean = beanCache.get(name);
if (bean != null) {
return bean;
}
BeanDefinition beanDefinition = beanDefinitionHashMap.get(name);
String beanClass = beanDefinition.getBeanClass();
try {
Class className = Class.forName(beanClass);
bean = className.newInstance();
this.applyPropertyValues(bean, beanDefinition);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if (bean != null){
beanCache.put(name, bean);
}
return bean;
}
对象属性的injection
通过applyPropertyValues这个方法我们可以继承BeanFactory来实现对象属性的injection。首先通过泛型取到class里的field然后根据BeanDefinition注入对应的值。
protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception {
Field[] fields = bean.getClass().getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
Autowired autowiredAn = field.getAnnotation(Autowired.class);
my.annotation.Field myfieldAn = field.getAnnotation(my.annotation.Field.class);
if (autowiredAn != null){
field.set(bean, this.getBean(autowiredAn.name()));
} else if (myfieldAn != null){
Type type = field.getGenericType();
if (type.getTypeName() == "int"){
field.set(bean, Integer.valueOf(myfieldAn.value()));
}else {
field.set(bean, String.valueOf(myfieldAn.value()));
}
}
else {
for (BeanProperty beanProperty : beanDefinition.getBeanProperties()) {
if (field.getName().equals(beanProperty.getName())) {
if (beanProperty.getRefBean() != null) {
field.set(bean, this.getBean(beanProperty.getRefBean()));
} else {
field.set(bean, beanProperty.getValue());
}
break;
}
}
}
}
}