提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
目录
前言
通过手写模拟Spring源码了解Spring底层源码启动原理与工作工程。第一部分为通过@ComponetScan扫描相应的包获取Bean实例。这里未设置@Scope,默认都是单例。
一、目录结构
二、相关部分代码
1.Spring启动类
public class Test {
public static void main(String args[]){
try {
ApplicationContext applicationContext=new ApplicationContext(AppConfig.class);
Userservice bean = (Userservice)applicationContext.getBean("userservice");
bean.test();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2.AppConfig类和ComponentScan注解
@ComponentScan("com.example.service")
public class AppConfig {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value() default "";
}
3.
BeanDefinition类
public class BeanDefinition {
private Class clazz;
public BeanDefinition(Class clazz) {
this.clazz = clazz;
}
public BeanDefinition() {
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
}
4.ApplicationContext类
获取配置类的注解扫描路径,通过类加载器获取该路径下的资源,然后遍历资源下的各个文件,判断当前类是不是一个Bean实例,将BeanName和BeanDefinition对象存储到Map集合中。然后遍历该Map集合,添加到单例池中。
public ApplicationContext(Class configClass) throws ClassNotFoundException {
this.configClass = configClass;
ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String value = annotation.value();
System.out.println(value);
value=value.replace('.','/');
// 类加载器应用
ClassLoader classLoader=ApplicationContext.class.getClassLoader();
// 获取类加载器下当前目录下的资源
URL resource = classLoader.getResource(value);
File file=new File(resource.getFile());
if(file.isDirectory()){
File[] files=file.listFiles();
for(File f:files){
// 获取当前资源下的class文件
String absolutePath = f.getAbsolutePath();
if(absolutePath.endsWith(".class")){
String className=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
className=className.replace("\\",".");
Class<?> loadClass = classLoader.loadClass(className);
if(loadClass.isAnnotationPresent(Componet.class)){
Componet declaredAnnotation = loadClass.getDeclaredAnnotation(Componet.class);
String value1 = declaredAnnotation.value();
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setClazz(loadClass);
beanDefinitionHashMap.put(value1,beanDefinition);
}
}
}
}
for(String beanName:beanDefinitionHashMap.keySet()){
BeanDefinition beanDefinition=beanDefinitionHashMap.get(beanName);
Object bean = createBean(beanDefinition);
hashMap.put(beanName,bean);
}
}
createBean方法
public Object createBean(BeanDefinition beanDefinition){
Class clazz=beanDefinition.getClazz();
try {
Object o = clazz.getDeclaredConstructor().newInstance();
return o;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
getBean方法
public Object getBean(String beanName){
if(beanDefinitionHashMap.containsKey(beanName)){
BeanDefinition beanDefinition = beanDefinitionHashMap.get(beanName);
Object o = hashMap.get(beanName);
return o;
}
else {
throw new NullPointerException();
}
}
总结
通过简单手写Spring源码,有了更深的理解。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/197085.html