模拟Spring创建Bean流程
温馨提示:
本文最后更新于 2023年09月06日,已超过 504 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
流程说明
main方法中,我们模拟使用Spring获取我们定义的bean流程;
定义Spring容器:
首先,定义一个Spring容器,命名为ZhuziApplicationContext,并定义我们的构造方法(参数:配置文件或配置类);
定义配置类:
这里我们采用配置类方式实现;所以我们需要定义一个配置类:SpringConfig;
定义注解:
- 定义@ComponentScan来标识Spring的扫描范围(路径);
- 定义@Component来标识当前Bean需要交给Spring管理;
- 定义@Scope来标识当前Bean是单例还是多例;
定义Bean
定义一个Bean交给Spring来管理,如:UserService;
代码
Main
public class Main {
public static void main(String[] args) {
ZhuziApplicationContext zhuziApplicationContext = new ZhuziApplicationContext(SpringConfig.class);
UserService userService = (UserService) zhuziApplicationContext.getBean("userService");
}
}
自定义注解
@ComponentScan
//注解位置
@Target(ElementType.TYPE)
//生效时间
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String[] value() default {};
}
@Component
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
@Scope
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default "singleton";
}
定义配置类
import com.zhuzi.spring.ComponentScan;
@ComponentScan(value = "com.zhuzi.service")
public class SpringConfig {
}
定义Spring容器
1.读取配置信息;
2.判断是否交给Spring加载;
3.如果交给Spring,则扫描配置路径(编译文件)下所有的类;
4.判断当前类是否交给Spring管理
5.如果是,保存所有Bean定义信息;
6.循环所有Bean定义,实例化单例Bean;
7.多例Bean每次获取时实例化;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class ZhuziApplicationContext {
private Class clazz;
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> singletonMap = new ConcurrentHashMap<>();
private static final String SINGLETON = "singleton";
public ZhuziApplicationContext(Class clazz) {
this.clazz = clazz;
// Spring容器启动要做什么?
// 扫描
if (clazz.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScan = (ComponentScan) clazz.getAnnotation(ComponentScan.class);
String[] paths = componentScan.value();
for (String path : paths) {
path = path.replace(".", "/");
// 获取类加载器
ClassLoader classLoader = clazz.getClassLoader();
URL resource = classLoader.getResource(path);
assert resource != null;
// 获取File
File file = new File(resource.getFile());
// 判断是否是文件夹
if (file.isDirectory()) {
File[] files = file.listFiles();
assert files != null;
for (File file1 : files) {
// 获取所有的文件
String absolutePath = file1.getAbsolutePath();
if (absolutePath.endsWith(".class")) {
String className = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
className = className.replace("\\", ".");
Class<?> aClass;
try {
aClass = classLoader.loadClass(className);
if (aClass.isAnnotationPresent(Component.class)) {
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClazz(aClass);
if (aClass.isAnnotationPresent(Scope.class)) {
Scope annotation = aClass.getAnnotation(Scope.class);
beanDefinition.setScope(annotation.value());
} else {
beanDefinition.setScope(SINGLETON);
}
Component component = aClass.getAnnotation(Component.class);
String beanName = component.value();
if (Objects.equals("", beanName)) {
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
// 实例化单例Bean
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (Objects.equals(SINGLETON, beanDefinition.getScope())) {
this.getSingletonBean(beanName);
}
}
}
private Object createBean(BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getClazz();
try {
return clazz.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (Objects.isNull(beanDefinition)) {
throw new NullPointerException();
}
if (Objects.equals(SINGLETON, beanDefinition.getScope())) {
return this.getSingletonBean(beanName);
}
return this.createBean(beanDefinition);
}
/**
* 获取单例Bean
* @param beanName
* @return
*/
private Object getSingletonBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (Objects.equals(SINGLETON, beanDefinition.getScope())) {
Object bean = singletonMap.get(beanName);
if (Objects.isNull(bean)) {
bean = this.createBean(beanDefinition);
singletonMap.put(beanName, bean);
}
return bean;
}
throw new RuntimeException();
}
}
正文到此结束
- 本文标签: spring java
- 本文链接: https://www.58cto.cn/article/6
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 模拟Spring创建Bean流程 - https://www.58cto.cn/article/6