(参阅5.3spring源码简单实现)
许久未曾专注的写过文章。实在有些对不住,也想了很长时间了,于是就专门输出点东西吧。言归正传。此间代码查阅于【spring3.5.10】网上资料很多关于编译spring源码的,故此省略。
从spring-context的测试包下开始。
AnnotationConfigApplicationContext 做了三件事,
第一个扫描包
主要目的获取> BeanDefinition
第二个刷新容器
第三则是获取容器中的Bean
故而,模拟实现也可以根据此来。
开始项目,新建项目
无任何引用的jar包
具体的结构如下
直接看结果,TeacherService,StudentService都注入并有值,就此简单实现完成。
主要代码块
public AnnotationApplicationContext(Class clazz) {
scanner(clazz);
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
//单例
if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(beanDefinition.getScope()){
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
//主要扫描单例非懒加载的Bean,扫描包路径,添加到BeanDefinition中,相当于容器;后续或根据Definition生成对应类
private void scanner(Class clazz) {
if (clazz.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) clazz.getAnnotation(ComponentScan.class);
String value = componentScanAnnotation.value();
String replace = value.replace(".", "/");
//加载class
ClassLoader classLoader = AnnotationApplicationContext.class.getClassLoader();
URL url = classLoader.getResource(replace);
File mainFile = new File(url.getFile());
if (mainFile.isAbsolute()) {
for (File file : mainFile.listFiles()) {
String absolutePath = file.getAbsolutePath();
String s = absolutePath.substring(absolutePath.indexOf("cn"), absolutePath.indexOf(".class"))
.replace("\\", ".");
try {
Class<?> aClass = classLoader.loadClass(s);
if (aClass.isAnnotationPresent(Component.class)) {
Component componentAnnotation = aClass.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if (Objects.equals("", beanName)) {
// 此处注意,如果类为ABTest 则生成的Bean为ABTtest
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
BeanDefinition definition = new BeanDefinition();
definition.setBeanClass(aClass);
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
definition.setScope(annotation.value());
} else {
definition.setScope(ConfigurableBeanFactory.SCOPE_SINGLETON);
}
beanDefinitionMap.put(beanName, definition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
//扫描完成,根据BeanDefinition生成对象
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getBeanClass();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
//后续还有初始化Aware操作;SmartInitializingSingleton单例非懒加载之后操作;BeanFactory初始化前,后操作;InitializingBean>afterPropertiesSet();PostConstruct。
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return instance;
}
//获取容器中的Bean
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new RuntimeException("不存在该bean" + beanName);
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
String scope = beanDefinition.getScope();
if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(scope)) {
Object singletonBean = singletonObjects.get(beanName);
//此处很重要,属性填充的时候,可能不存在,需要重新创建并放入容器缓存
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}