1. 创建一个工程及初始化
-
创建Java工程
-
创建对应的包
config:为配置类包
service:定义的将要被自己写的Spring容器管理的组件bean
spring:里面定义自己写的Spring的类文件,包含子包anno注解包
test:定义测试类
2. 模仿我们写Spring程序时创建测试类
package com.cjp.test;
import com.cjp.config.AppConfig;
import com.cjp.service.UserInterface;
import com.cjp.spring.ApplicationContext;
import java.lang.reflect.InvocationTargetException;
/**
* @author 曹见朋
* @create 2023-11-23-9:30
*/
public class MySpringTest {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);
UserInterface UserInterface = (UserInterface) applicationContext.getBean("userService");
System.out.println("获取到的bean: " + UserInterface);
UserInterface.test();
}
}
在这里,ApplicationContext就是我们将要手写的Spring上下文类,这里是模仿传入一个配置类参数,即全注解开发。
3. 开始实现ApplicationContext
- ApplicationContext内容
package com.cjp.spring;
import com.cjp.config.AppConfig;
import com.cjp.spring.anno.Autowired;
import com.cjp.spring.anno.Component;
import com.cjp.spring.anno.ComponentScan;
import com.cjp.spring.anno.Scope;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author 曹见朋
* @create 2023-11-23-9:24
*/
public class ApplicationContext {
private Class appConfigClass;
private ConcurrentHashMap<String, BeanDefinition> beanDefinitionConcurrentHashMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Object> singletonBeanConcurrentHashMap = new ConcurrentHashMap<>();
private ArrayList<BeanPostProcessor> beanPostProcessorArrayList = new ArrayList<>();
public ApplicationContext(Class<AppConfig> appConfigClass) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
this.appConfigClass = appConfigClass;
scan(appConfigClass);
// 把单例bean放入单例bean容器
for (String beanName : beanDefinitionConcurrentHashMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
//单例的
Object bean = createBean(beanName, beanDefinition);
singletonBeanConcurrentHashMap.put(beanName, bean);
}
}
}
private void scan(Class<AppConfig> appConfigClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
ComponentScan componentScanAnnotation = appConfigClass.getAnnotation(ComponentScan.class);
String classPath = componentScanAnnotation.value();
String classPath_file = classPath.replace(".", "/");
ClassLoader classLoader = ApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(classPath_file);
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
String file_name = file1.getName();
String class_path_file = classPath + "." + file_name.substring(0, file_name.length() - 6);
// System.out.println(class_path_file); //此时获取的是全限定类名:com.cjp.serviceCartService
Class<?> aClass = Class.forName(class_path_file);
if (aClass.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
Object instance = aClass.newInstance();
beanPostProcessorArrayList.add((BeanPostProcessor) instance);
}
String bean_name = aClass.getAnnotation(Component.class).value();
if (bean_name.equals("") || bean_name == null) {
bean_name = Introspector.decapitalize(aClass.getSimpleName());
// System.out.println("默认的bean的名字:"+bean_name);
}
// System.out.println("应当加载该Bean "+class_path_file);
// 先定义BeanDefinition
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(aClass);
// 没有scope注解,默认的单例的
if (aClass.isAnnotationPresent(Scope.class)) {
// 有scope注解,判断scope注解的值,如果为single,则为单例,否则为prototype是多例
String scope_value = aClass.getAnnotation(Scope.class).value();
if (scope_value.equals("singleton")) {
beanDefinition.setScope("singleton");
} else {
beanDefinition.setScope("prototype");
}
} else {
beanDefinition.setScope("singleton");
}
// System.out.println(beanDefinition);
beanDefinitionConcurrentHashMap.put(bean_name, beanDefinition);
}
}
}
}
// 此方法体现了bean的生命周期
private Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class type = beanDefinition.getType();
Object instance = type.getConstructor().newInstance();
// 实现依赖注入
for (Field field : type.getDeclaredFields()) {
System.out.println(field);
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
Class<?> field_type = field.getType();
String simpleName = field_type.getSimpleName();
String capitalize = Introspector.decapitalize(simpleName); //bean的名字
Object bean = getBean(capitalize);
if (bean != null) {
field.set(instance, bean);
} else {
throw new RuntimeException("依赖注入错误,未找到" + field_type);
}
}
}
// Aware
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
// 初始化前的前置处理器
for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean) instance).initialBean();
}
// 初始化后的后置处理器
for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
}
// 初始化后 AOP BeanPostProcessor Bean后置处理器
return instance;
}
public Object getBean(String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
} else {
String scope = beanDefinition.getScope();
//单例
if (scope.equals("singleton")) {
Object bean = singletonBeanConcurrentHashMap.get(beanName);
if (bean == null) {
Object new_bean = createBean(beanName, beanDefinition);
singletonBeanConcurrentHashMap.put(beanName, new_bean);
return new_bean;
}
return bean;
} else { // 多例
return createBean(beanName, beanDefinition);
}
}
}
}
- 注解类
package com.cjp.spring.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 曹见朋
* @create 2023-11-23-9:25
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value();
}
package com.cjp.spring.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 曹见朋
* @create 2023-11-23-9:25
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
package com.cjp.spring.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 曹见朋
* @create 2023-11-23-9:25
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
String value() default "";
}
package com.cjp.spring.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 曹见朋
* @create 2023-11-23-9:52
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default "singleton";
}
- 回调接口
package com.cjp.spring;
/**
* @author 曹见朋
* @create 2023-11-23-11:24
*/
public interface BeanNameAware {
void setBeanName(String beanName);
}
package com.cjp.spring;
/**
* @author 曹见朋
* @create 2023-11-23-11:34
*/
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(String beanName, Object bean);
Object postProcessAfterInitialization(String beanName, Object bean);
}
package com.cjp.spring;
/**
* @author 曹见朋
* @create 2023-11-23-11:29
*/
public interface InitializingBean {
public void initialBean();
}
- 组件类
- 配置类
package com.cjp.config;
import com.cjp.spring.anno.ComponentScan;
/**
* @author 曹见朋
* @create 2023-11-23-9:25
*/
@ComponentScan("com.cjp.service")
public class AppConfig {
}