博客
关于我
Spring源码 20 手写模拟源码
阅读量:37200 次
发布时间:2020-08-01 07:19:27

本文共 8790 字,大约阅读时间需要 29 分钟。

参考源

《Spring源码深度解析(第2版)》

版本

本文章基于 Spring 5.3.15


项目地址

模拟 Spring

注解

自动装配

Autowired

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Autowired {}

组件

Component

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Component {
String value() default "";
}

组件扫描

ComponentScan

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ComponentScan {
String value() default "";
}

范围

Scope

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Scope {
String value() default "";}

Bean 定义信息

BeanDefinition

public class BeanDefinition {
/**
 * 类型
 */
private Class type;
/**
 * 范围
 */
private String scope;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}}

Bean 名称感知

BeanNameAware

public interface BeanNameAware {
/**
 * 设置 Bean 名称
 * @param beanName Bean名称
 */
void setBeanName(String beanName);}

Bean 后置处理器

BeanPostProcessor

public interface BeanPostProcessor {
/**
 * 初始化前
 * @param beanName Bean名称
 * @param bean Bean对象
 * @return
 */
Object postProcessBeforeInitialization(String beanName, Object bean);
/**
 * 初始化后
 * @param beanName Bean名称
 * @param bean Bean对象
 * @return
 */
Object postProcessAfterInitialization(String beanName, Object bean);}

初始化 Bean

InitializationBean

public interface InitializationBean {
/**
 * 属性设置后
 */
void afterPropertiesSet();
}

注解配置应用上下文

AnnotationConfigApplicationContext

public class AnnotationConfigApplicationContext {
/**
 * 配置的类
 */
private Class configClass;
/**
 * Bean 后置处理器列表
 */
private List  beanPostProcessorList = new ArrayList<>();
/**
 * Bean 定义信息池
 */
private ConcurrentHashMap  beanDefinitionMap = new ConcurrentHashMap<>();
/**
 * 单例池
 */
private ConcurrentHashMap  singletonObjects = new ConcurrentHashMap<>();
public AnnotationConfigApplicationContext(Class configClass) {
this.configClass = configClass;
/*
扫描 -> BeanDefinition -> beanDefinitionMap
 */
// 是否有 @ComponentScan 注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 注解中的路径
String path = componentScan.value();
// 处理路径
path = path.replace(".", "/");
// 类加载器
ClassLoader classLoader = AnnotationConfigApplicationContext.class.getClassLoader();
// 资源
URL resource = classLoader.getResource(path);
// 文件
File file = new File(resource.getFile());
// 如果为目录
if (file.isDirectory()) {
// 文件列表
File[] files = file.listFiles();
for (File f : files) {
// 绝对路径
String fileName = f.getAbsolutePath();
// 是否为 class 文件
if (fileName.endsWith(".class")) {
// 类名 cn\sail\test\文件名
String className = fileName.substring(fileName.indexOf("cn"), fileName.indexOf(".class"));
// 处理路径
className = className.replace("\\", ".");
try {
Class  clazz = classLoader.loadClass(className);
// 是否有 @Component 注解
if (clazz.isAnnotationPresent(Component.class)) {
// 接口和类是否相同或者是否为其超类或超接口
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
beanPostProcessorList.add(instance);
}
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
// 是否有 @Scope 注解
if (clazz.isAnnotationPresent(Scope.class)) {
// 如果有,以传入的模式为准
Scope scope = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
} else {
// 如果没有,默认为单例模式
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
// 实例化单例 Bean
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
// 如果为单例模式,将 BeanDefinition 放入单例池中,下次直接从池中取,以保证单例
if ("singleton".equals(beanDefinition.getScope())) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
/**
 * 创建 Bean
 * @param beanName Bean 名称
 * @param beanDefinition Bean 定义信息
 * @return Bean 对象
 */
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field f : clazz.getDeclaredFields()) {
// 是否有 @Autowired 注解
if (f.isAnnotationPresent(Autowired.class)) {
// 忽略访问修饰符限制
f.setAccessible(true);
// 注入
f.set(instance, getBean(f.getName()));
}
}
// Aware
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
// 初始化前
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
}
// 初始化
if (instance instanceof InitializationBean) {
((InitializationBean) instance).afterPropertiesSet();
}
// 初始化后
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
} else {
String scope = beanDefinition.getScope();
if ("singleton".equals(scope)) {
Object bean = singletonObjects.get(beanName);
// 如果单例池中没有对应 Bean,创建 Bean 后再放入池中
if (bean == null) {
bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
return bean;
} else {
// 如果不是单例模式,直接创建 Bean
return createBean(beanName, beanDefinition);
}
}
}
}

使用 Spring

应用配置

AppConfig

@ComponentScan("cn.sail.test")public class AppConfig {}

用户服务

UserInterface

public interface UserInterface {
/**
 * 测试
 */
void test();}

用户服务实现类

UserService

@Componentpublic class UserService implements UserInterface{
@Autowired
private OrderService orderService;
@Override
public void test() {
System.out.println(orderService);
}}

排序服务

OrderService

@Componentpublic class OrderService {}

Bean 后置处理器

MyBeanPostProcessor

@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {
/**
 * 初始化前
 *
 * @param beanName
 * @param bean
 * @return
 */
@Override
public Object postProcessBeforeInitialization(String beanName, Object bean) {
if ("userService".equals(beanName)) {
System.out.println("1111");
}
return bean;
}
/**
 * 初始化后
 *
 * @param beanName
 * @param bean
 * @return
 */
@Override
public Object postProcessAfterInitialization(String beanName, Object bean) {
if ("userService".equals(beanName)) {
Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("切面逻辑");
return method.invoke(bean, args);
}
});
return proxyInstance;
}
return bean;
}}

测试

Test

public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
}}

转载地址:http://yypwwy.baihongyu.com/

你可能感兴趣的文章
铂金钻石组第五题
查看>>
第二题
查看>>
第三题
查看>>
第四题
查看>>
第五题(打完自闭)
查看>>
第六题
查看>>
第七题
查看>>
VUE获取元素高度的方法
查看>>
vue中使用vconsole,适合在公众号手机页面的调试工具
查看>>
element-ui DateTimePicker设置只能选择当前时间之前或之后的时间
查看>>
vue中封装公共的方法
查看>>
vue中实现购物页面侧栏分类随滚动自动激活侧栏分类,商品页面侧栏分类和页面滚动联动demo
查看>>
推荐四种好看的加载动画,需要的自取
查看>>
点击获取验证码并登录的实现和验证原理
查看>>
vue中用户自定义短信模板设置,功能为点击添加有光标时在光标后面拼接数据,没光标时在短信模板后面直接拼接数据
查看>>
vue 路由跳转记住滚动位置,返回时回到上次滚动位置(第一种亲测有效,且数据状态也会很好的保存,以及滚动位置)
查看>>
nvm一个node版本管理工具
查看>>
vue中实现轮询功能,常用于监听支付状态
查看>>
js判断日期大小
查看>>
vue和uniapp中页面数据不更新,js变量更新了,视图数据却没变
查看>>