参照初始Spring的理解,https://blog.csdn.net/angbug/article/details/120440761,简单模拟Spring框架
/**
* 模拟Spring框架
* 1.创建容器:简单实现基本的四个注解
* 1.1 @ComponentScan 定义扫描的目录范围
* 1.2 @Component 定义要被Spring管理的class
* 1.3 @Autowired 定义spring管理的对象需要注入的依赖
* 1.4 @Scope 定义对象是否单例
* 2.扫描@ComponentScan定义的目录里的class文件,
* 2.1把含@Component注解的class包装BeanDefinition,放入BeanDefinition集合
* BeanDefinition{className-类名,scope-是否单例}
* 2.2 把BeanPostProcessor生成实例对象,放入BeanPostProcessor集合
* 3.遍历BeanDefinition集合,把单例的对象初始化,并放入缓存
* 3.1 创建对象
* 3.1 执行 InitializingBean接口功能
* 3.2 执行 BeanPostProcessor接口功能
* 4.提供getBean方法,供使用
* 5 通过BeanPostProcessor和JDK动态代理模拟AOP功能
*/
- 四个注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
2.两个功能接口
public interface InitializingBean {
void afterPropertiesSet();
}
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
3.一个包装class的类定义,这里只简单记录两个属性,类名和是否单例
public class BeanDefinition {
private Class className;
private String scope;
public void setClassName(Class className) {
this.className = className;
}
public Class getClassName() {
return className;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
4.spring容器
public class ApplicationContextDiy {
// 配置类
private Class configClass;
// BeanDefinition 集合
private Map<String,BeanDefinition> beanDefinitionMap= new HashMap<>();
// 生成的单例对象集合
private Map<String, Object> singletonObjects = new HashMap<>();
// BeanPostProcessor对象集合
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
// 1.构造函数
public ApplicationContextDiy(Class configClass) {
1. 扫描加载class,把class封装成BeanDefinition,放入BeanDefinition集合
scan(configClass);
2.遍历BeanDefinition集合,初始化单例对象,放入缓存
singletonObjects
}
// 2.扫描指定目录,加载扫描到的class,并把记录缓存class信息
public void scan(Class configClass){
1把含@Component注解的class包装BeanDefinition,放入BeanDefinition集合
2. 把BeanPostProcessor生成实例对象,放入BeanPostProcessor集合
}
// 3.创建对象,实际用工厂模式创建
private Object createBean(String beanName, BeanDefinition beanDefinition){
1 创建对象
2 执行 InitializingBean接口功能
3 执行 BeanPostProcessor接口功能
}
// 4.获取bean对象
public Object getBean(String beanName){
1 单例直接从缓存里取
2 原型多例新创建实例bean对象
}
}
4.1 构造函数
// 1.构造函数
public ApplicationContextDiy(Class configClass) {
// 获取配置类
this.configClass = configClass;
// 扫描加载class,把class封装成BeanDefinition
scan(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);
}
}
}
4.2 扫描指定目录,加载扫描到的class,并把记录缓存class信息
// 2.扫描指定目录,加载扫描到的class,并把记录缓存class信息封装成BeanDefinition
public void scan(Class configClass){
if (configClass.isAnnotationPresent(ComponentScan.class)) {
// 获取 ComponentScan配置的扫描目录路径
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".", "/");
// 读取扫描目录里的文件
ClassLoader classLoader = ApplicationContextDiy.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
// 加载class
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
// 如果class由Component注解 缓存class信息,等待后面实例化
if (clazz.isAnnotationPresent(Component.class)) {
Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setClassName(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
4.3 创建对象,实际用工厂模式创建
// 3.简略创建对象,实际用工厂模式创建
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getClassName();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
field.set(instance, getBean(field.getName()));
}
}
// 执行 BeanPostProcessor 初始化前置方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
//执行 InitializingBean 初始化方法
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
// 执行 BeanPostProcessor 初始化后置方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
4.4 获取bean对象
// 4.获取bean对象
public Object getBean(String beanName){
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
// 单例直接从缓存里取实例bean对象
if (beanDefinition.getScope().equals("singleton")) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型多例新创建实例bean对象
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
5 使用BeanPostProcessor和JDK动态代理模拟AOP功能
@Component
public class AopBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) {
if ( "userService".equals(beanName)) {
Object proxyInstance = Proxy.newProxyInstance(AopBeanPostProcessor.class.getClassLoader(),
bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 切面
Object result = null;
if ("test".equals(method.getName())) {
System.out.println("userService切面逻辑前");
result = method.invoke(bean, args);
System.out.println("userService切面逻辑后");
}else{
result = method.invoke(bean, args);
}
return result;
}
});
return proxyInstance;
}
return bean;
}
}
6.三个测试类
@Component
public class OrderService {
}
//这里为了简单 使用jdk的动态代理实现AOP必须用接口
public interface UserInterface {
public void test();
}
@Component
public class UserService implements UserInterface{
@Autowired
public OrderService orderService;
public void test(){
System.out.println("userService test running = " + orderService);
}
}
7.入口类
@ComponentScan("com.project")
public class MainEnter {
public static void main(String[] args) {
// 模拟Spring框架
ApplicationContextDiy applicationContext = new ApplicationContextDiy(MainEnter.class);
UserInterface userProxy = (UserInterface)applicationContext.getBean("userService");
System.out.println(userProxy);
userProxy.test();
}
}
运行结果
com.project.UserService@6537cf78
userService切面逻辑前
userService test running = com.project.OrderService@5afa04c
userService切面逻辑后
Process finished with exit code 0