手写Spring源码-1.ApplicationContext
- 1.自定义Component注解
- 2.自定义ComponentScan注解
- 3.自定义Scope注解
- 4.自定义BeanDefinition类
- 5.自定义ApplicationContext类
- 5.1流程图
- 5.2.代码
- 自定义Component注解
- 自定义ComponentScan注解
- 自定义Scope注解
- 自定义BeanDefinition类
- 自定义ApplicationContext类
1.自定义Component注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value();
}
2.自定义ComponentScan注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value();
}
3.自定义Scope注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value();
}
4.自定义BeanDefinition类
public class BeanDefinition {
//bean的类型
private Class clazz;
//bean的作用域
private String scope;
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
5.自定义ApplicationContext类
5.1流程图
5.2.代码
package com.spring;
import java.io.File;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class TanminApplicationContext {
//配置文件的Class
private Class configClass;
//单例池
private ConcurrentHashMap singletonObjects=new ConcurrentHashMap<>();
//存储Bean定义对象的map
private ConcurrentHashMap beanDefinitionMap = new ConcurrentHashMap<>();
public TanminApplicationContext(Class configClass) throws ClassNotFoundException {
this.configClass = configClass;
//解析配置文件
//解析@ComponentScan注解,得到扫描路径
//获取 ComponentScan 注解对象
//Annotation[] getDeclaredAnnotations()--
//扫描
scan(configClass);
//循环创建Bean对象
//Set> entrySet()--返回此映射所包含的映射关系的 Set 视图
for (Map.Entry entry:beanDefinitionMap.entrySet()){
//获取beanName
String beanName = entry.getKey();
//获取beanDefinition
BeanDefinition beanDefinition = entry.getValue();
//判断是否是单例bean
if (beanDefinition.getScope().equals("singleton")){
//创建bean
Object bean = createBean(beanDefinition);
//存入singletonObjects单例池
singletonObjects.put(beanName,bean);
}
}
}
//创建Bean对象
public Object createBean(BeanDefinition beanDefinition){
//获取Bean的类型
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
//扫描对象
private void scan(Class configClass) throws ClassNotFoundException {
//获取ComponentScan对象
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
//获取ComponentScan注解属性-扫描路径
String path = componentScanAnnotation.value();
//输出扫描路径-测试
// System.out.println(path);
//获取类加载器
ClassLoader classLoader = TanminApplicationContext.class.getClassLoader();
//输出类加载器-测试
// System.out.println(classLoader);
//获取资源路径
URL resource = classLoader.getResource("com/tanmin/service");
// System.out.println(resource);
// System.out.println(resource.getFile());
//转换文件对象
File file = new File(resource.getFile());
//测试此抽象路径名表示的文件是否是一个目录
if (file.isDirectory()){
//返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
File[] files = file.listFiles();
//循环获取每个文件
for (File f : files) {
// System.out.println(f);
//返回此抽象路径名的绝对路径名字符串
String filename = f.getAbsolutePath();
//boolean endsWith(String suffix)--测试此字符串是否以指定的后缀结束
if (filename.endsWith(".class")) {
//int indexOf(int ch)--返回指定字符在此字符串中第一次出现处的索引
//String substring(int beginIndex, int endIndex)--返回一个新字符串,它是此字符串的一个子字符串。
String className = filename.substring(filename.indexOf("com"), filename.indexOf(".class"));
//String replace(char oldChar, char newChar)--用 newChar 替换此字符串中出现的所有 oldChar 得到一个新的字符串
className = className.replace("\", ".");
// System.out.println(className);
//Class loadClass(String name) --使用指定的二进制名称来加载类
Class> clazz = classLoader.loadClass(className);
//boolean isAnnotationPresent(Class annotationClass)--如果指定类型的注释存在于此元素上,则返回 true,否则返回 false
//判断当前类是否是一个Bean
if (clazz.isAnnotationPresent(Component.class)){
//创建BeanDefinition对象
BeanDefinition beanDefinition = new BeanDefinition();
//设置BeanDefinition的clazz属性
beanDefinition.setClazz(clazz);
//获取Component对象
Component componentAnnotation = clazz.getDeclaredAnnotation(Component.class);
//获取Bean的名称
String beanName = componentAnnotation.value();
//解析类,判断当前Bean是单例还是多例
if (clazz.isAnnotationPresent(Scope.class)){
//获取Scope对象
Scope scopeAnnotation = clazz.getDeclaredAnnotation(Scope.class);
//如果有值,则是多例对象
beanDefinition.setScope(scopeAnnotation.value());
}else {
//如果没有值,则是单例对象
beanDefinition.setScope("singleton");
}
//存储Bean对象的名称和Bean的定义
beanDefinitionMap.put(beanName,beanDefinition);
}
// System.out.println(filename);
}
}
}
}
//获取Bean对象
public Object getBean(String beanName) {
//先判断beanDefinitionMap中是否包含beanNname
if (beanDefinitionMap.containsKey(beanName)){
//如果存在对应的bean,获取beanDefinition
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
//判断Bean是单例还是多例
if(beanDefinition.getScope().equals("singleton")){
//如果是单例对象,则从单例池中根据beanbean获取对象
Object o = singletonObjects.get(beanName);
return o;
}else {
//如果不是单例对象,创建bean
Object bean = createBean(beanDefinition);
return bean;
}
}else {
//如果不存在对应的bean
throw new NullPointerException();
}
}
}