手动模拟Spring,实现了单例、原型Bean的创建,简单依赖注入,根据名称获取Bean实例对象,初始化与后置处理器等基本功能
组件扫描注解,在配置类上添加,用于扫描指定包名下的组件
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}组件注解,在需要被扫描的类上添加,用于指定该Bean的名称
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}作用域注解,用于指定该Bean对象是单例或原型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}自动注入注解,可添加至字段上
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
String value() default "";
}初始化方法接口,实现该接口方法进行初始化
public interface InitializingBean {
void afterPropertiesSet();
}Bean后置处理器,实现初始化前后的操作
public interface BeanPostProcessor {
default Object postProcessorBeforeInitializing(Object bean, String beanName) {
return bean;
}
default Object postProcessorAfterInitializing(Object bean, String beanName) {
return bean;
}
}该类为Bean的定义对象,存放Bean的相关信息
public class BeanDefinition {
private Class<?> type; // Bean类型
private String scope; // Bean作用域
private boolean bLazy; // 是否懒加载
// getter & setter ...
}该类为Spring容器,用于创建和管理Bean对象
public class MySpringApplicationContext {
// ...
}添加构造方法MySpringApplicationContext,用于读取配置类
private final Class<?> configClass; // 配置类
public MySpringApplicationContext(Class<?> configClass) {
this.configClass = configClass;
}添加扫描方法scan,通过扫描配置类上@ComponentScan注解内的值来获取查找需要创建Bean对象的类,并将该Bean信息添加到BeanDefinitionMap中
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); // Bean定义Map
public MySpringApplicationContext(Class<?> configClass) {
// ...
scan(configClass);
}
public void scan(Class<?> configClass) {
// 扫描注解获取文件路径
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
String scanPath = componentScan.value();
scanPath = scanPath.replace(".", "/");
ClassLoader classLoader = configClass.getClassLoader();
URL resource = classLoader.getResource(scanPath);
if (Objects.nonNull(resource)) {
File file = new File(resource.getFile());
if (file.isDirectory()) {
// 遍历目录下文件
for (File f : Objects.requireNonNull(file.listFiles())) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");
// 加载类文件获取注解
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
// Bean信息添加到BeanDefinitionMap中
BeanDefinition beanDefinition = new BeanDefinition();
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
if ("".equals(beanName)){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scope = clazz.getAnnotation(Scope.class);
String value = scope.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
}
}添加创建方法createBean,该方法通过Bean的定义类BeanDefinition来创建相应的Bean对象
修改构造方法MySpringApplicationContext,在构造时直接创建单例Bean对象,并将该对象存入单例池singletonObjects中,用于后续单例对象的调用
private final Map<String, Object> singletonObjects = new HashMap<>(); // 单例池
public Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> clazz = beanDefinition.getType();
Object instance;
try {
instance = clazz.getConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return bean;
}
public MySpringApplicationContext(Class<?> configClass) {
// ...
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}添加getBean方法获取Bean对象,若为单例对象则从线程池中直接获取,若为原型对象则通过返回一个新的Bean对象,此时可以对单例与原型Bean进行基本的创建使用功能
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new RuntimeException("Bean不存在");
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
String scope = beanDefinition.getScope();
if (scope.equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
// 解决依赖与单例Bean创建顺序不一致导致的从单例池返回结果为null的问题
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
}
if (scope.equals("prototype")) {
return createBean(beanName, beanDefinition);
}
return null;
}修改createBean方法,在创建Bean对象后通过反射进行依赖注入为属性赋值
public Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> clazz = beanDefinition.getType();
Object instance;
try {
instance = clazz.getConstructor().newInstance();
// 遍历属性,查看是否有依赖注入注解 Autowired
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return bean;
}修改createBean方法,实现初始化功能,实现InitializingBean接口并调用接口中的afterPropertiesSet方法
public Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> clazz = beanDefinition.getType();
Object instance;
try {
instance = clazz.getConstructor().newInstance();
// 遍历属性,查看是否有依赖注入注解 Autowired
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
// 初始化方法
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return instance;
}修改scan方法,在类获取到@Component注解后查询该类是否实现了BeanPostProcessor接口,若实现该接口则将该类添加到beanPostProcessors
缓存中,否则作为普通Bean添加信息到BeanDefinitionMap中
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>(); // 后置对象缓存列表
public void scan(Class<?> configClass) {
// ...
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
// BeanPostProcessor实现
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessors.add(beanPostProcessor);
}
// Bean信息添加到BeanDefinitionMap中
else {
BeanDefinition beanDefinition = new BeanDefinition();
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scope = clazz.getAnnotation(Scope.class);
String value = scope.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
// ...
} 修改createBean方法,在创建Bean初始化方法前后调用BeanPostProcessor的初始化前后方法postProcessorBeforeInitializing
和postProcessorAfterInitializing,通过该BeanPostProcessor可完成包括AOP、Aware在内的多种扩展方法
public Object createBean(String beanName, BeanDefinition beanDefinition) {
// ...
// 初始化前方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor.postProcessorBeforeInitializing(instance, beanName);
}
// 初始化方法
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
// 初始化后方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor.postProcessorAfterInitializing(instance, beanName);
}
// ...
}容器配置类,用于指定扫描的包
@ComponentScan(value = "com.example.service")
public class AppConfig {
}组件方法类,在类上添加Component注解指定该类为一个Bean容器
@Component
@Scope(value = "prototype")
public class TestService implements InitializingBean {
@Autowired
private TestWiredService testWiredService;
public void test() {
System.out.println("testService test!");
}
public void wiredTest() {
testWiredService.wiredTest();
}
@Override
public void afterPropertiesSet() {
System.out.println("testService 初始化");
}
}测试注入类
@Component
public class TestWiredService {
public void wiredTest() {
System.out.println("testWiredService test!");
}
}测试后置处理器
@Component
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessorBeforeInitializing(Object bean, String beanName) {
System.out.println(beanName + " 初始化前方法");
return BeanPostProcessor.super.postProcessorBeforeInitializing(bean, beanName);
}
@Override
public Object postProcessorAfterInitializing(Object bean, String beanName) {
System.out.println(beanName + " 初始化后方法");
return BeanPostProcessor.super.postProcessorAfterInitializing(bean, beanName);
}
}主测试类,用于调用Spring容器,获取容器中的Bean对象并调用方法
public class Test {
public static void main(String[] args) {
MySpringApplicationContext applicationContext = new MySpringApplicationContext(AppConfig.class);
TestService testService = (TestService) applicationContext.getBean("testService");
testService.test();
testService.wiredTest();
}
}测试结果打印
testWiredService 初始化前方法
testWiredService 初始化后方法
testService 初始化前方法
testService 初始化
testService 初始化后方法
testService test!
testWiredService test!