Spring - 手写模拟Spring底层原理

手写Spring

定义配置类AppConfig

@ComponentScan("com.spring.zsj")
public class AppConfig {@Beanpublic ApplicationListener applicationListener() {return new ApplicationListener() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println("接收到了一个事件"+event );}};}}

定义容器ZSJApplicationContext

public class ZSJApplicationContext {private Class configClass;private Map<String,BeanDefinition> beanDefinitionMap =new HashMap<>();//bean定义private Map<String,Object> singleObjects = new HashMap<>(); //单例池private List<BeanPostProcessor> beanPostProcessorList =new ArrayList<>(); //后置处理public ZSJApplicationContext(Class configClass)  {this.configClass = configClass;scanComponent(configClass);//找出单例beanfor (Map.Entry<String,BeanDefinition> entry: beanDefinitionMap.entrySet()) {String beanName = entry.getKey();BeanDefinition beanDefinition = entry.getValue();if(beanDefinition.equals("singleton")){Object bean = createBean(beanName, beanDefinition);singleObjects.put(beanName,bean);}}}private Object createBean(String beanName,BeanDefinition beanDefinition){Class clazz = beanDefinition.getType();Object newInstance = null;try {newInstance =  clazz.getConstructor().newInstance();//依赖注入for (Field field : clazz.getDeclaredFields()) {if (clazz.isAnnotationPresent(Autowired.class)) {field.setAccessible(true);field.set(newInstance, getBean(field.getName()));}}//执行回调方法if (newInstance instanceof  BeanNameAware){((BeanNameAware) newInstance).setBeanName(beanName);}//执行初始化前的方法for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {newInstance = beanPostProcessor.postProcessBeforeInitialization(newInstance, beanName);}//当前对象是否实例化了if(newInstance instanceof  InitializingBean){((InitializingBean) newInstance).afterPropertiesSet();}//执行初始化后的方法(例如Aop)for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {newInstance = beanPostProcessor.postProcessAfterInitialization(newInstance, beanName);}} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}return newInstance;}private void scanComponent(Class configClass) {if(configClass.isAnnotationPresent(ComponentScan.class)){ComponentScan annotation =(ComponentScan) configClass.getAnnotation(ComponentScan.class);String path = annotation.value();path = path.replace(".", "/");ClassLoader classLoader = ZSJApplicationContext.class.getClassLoader();URL resource = classLoader.getResource(path);File file = new File(resource.getFile());if(file.isDirectory()){//若是文件夹,则取出对应的文件for (File f: file.listFiles()) {String absolutePath = f.getAbsolutePath();//System.out.println(absolutePath);String com = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));String replace = com.replace("\\", ".");// System.out.println(replace);try {Class<?> clazz = classLoader.loadClass(replace);if(clazz.isAnnotationPresent(Component.class)){//clazz 是否实现了BeanPostProcessor接口if(BeanPostProcessor.class.isAssignableFrom(clazz)){BeanPostProcessor instance = (BeanPostProcessor)clazz.getConstructor().newInstance();beanPostProcessorList.add(instance);}//获取bean 的名字Component annotation1 = clazz.getAnnotation(Component.class);String beanName = annotation1.value();if("".equals(beanName)){String name = Introspector.decapitalize(clazz.getSimpleName());}BeanDefinition beanDefinition = new BeanDefinition();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);//   System.out.println(clazz);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}//   System.out.println(path);}}//通过bean名称获取bean对象public Object getBean(String beanName){if(!beanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(beanDefinition.getScope().equals("singleton")){Object singletonBean = singleObjects.get(beanName);if(singletonBean== null){singletonBean = createBean(beanName, beanDefinition);singleObjects.put(beanName,singletonBean);}return singletonBean;}else {//原型的Object prototypeBean = createBean(beanName, beanDefinition);return prototypeBean;}}
}

定义注解@Autowired  @Component  @Scope @ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {String value() default "";
}@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 "";
}

定义后置处理器BeanPostProcessor,用于初始化

public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName)  {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}
}

   定义ZSJBeanPostProcessor实现BeanPostProcesso

@Component
public class ZSJBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if(beanName.equals("userService")){Object proxyInstance = Proxy.newProxyInstance(ZSJBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//切面System.out.println("切面逻辑");return method.invoke(bean,args);}});return proxyInstance;}return bean;}
}

定义初始化接口InitializingBean

public interface InitializingBean {void afterPropertiesSet();
}

定义普通的类(可实例化成单例bean)

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface {@Autowiredprivate OrderService orderService;@ZSanValue("zhangsan")private String user;//圆型bean 表示多例beanpublic void test(){System.out.println(orderService);}//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

定义普通的类(可实例化成原型bean)

@Component("orderService")
@Scope("prototype")
public class OrderService {//圆型bean 表示多例beanpublic void test(){System.out.println("hello");}
}

定义启动类main


public class Test {public static void main(String[] args) {//非懒加载的单例bean
//        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//        UserService userService = (UserService)context.getBean("userService");
//
//        userService.test();ZSJApplicationContext context = new ZSJApplicationContext(AppConfig.class);UserInterface userService = (UserInterface)context.getBean("userService");userService.test();//      System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));//        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
//        reader.register(User.class);
//        System.out.println(context.getBean("user"));StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();propertyEditor.setAsText("1");User value =new User();System.out.println(value);}
}

BeanPostProcesso扩展使用方法

自定义注解@ZSanValue

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

使用注解时,将注解的值赋给属性:如

@ZSanValue("zhangsan")
private String user;

 实现后置处理器,并执行初始化前的操作,将自定义的注解值进行属性赋值

@Component
public class ZSanValueBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {for (Field field : bean.getClass().getDeclaredFields()) {if(field.isAnnotationPresent(ZSanValue.class)){field.setAccessible(true);try {field.set(bean,field.getAnnotation(ZSanValue.class).value());} catch (IllegalAccessException e) {e.printStackTrace();}}}return bean;}
}

回调方法使用BeanNameAware

定义回调接口

public interface BeanNameAware {void setBeanName(String name);
}

则实现类需要实现BeanNameAware接口

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface,BeanNameAware {@Autowiredprivate OrderService orderService;@ZSanValue("zhangsan")private String user;private String beanName;//圆型bean 表示多例beanpublic void test(){System.out.println(orderService);}@Overridepublic void setBeanName(String name) {this.beanName=name;}//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/127042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fabric二进制添加排序节点

目录 一、准备orderer11.1、注册orderer11.2、登记orderer11.3、登记orderer1的tls 二、添加orderer1的tls到系统通道三、获取最新的系统通道配置四、启动orderer1五、添加orderer1的endpoint到系统通道六、添加orderer1的tls到应用通道七、添加orderer1的endpoint到应用通道八…

【案例】3D地球(vue+three.js)

需要下载插件 <template><div class"demo"><div id"container" ref"content"></div></div> </template> <script> import * as THREE from three; // import mapJSON from ../map.json; import { Or…

pytorch 笔记:KLDivLoss

1 介绍 对于具有相同形状的张量 ypred​ 和 ytrue&#xff08;ypred​ 是输入&#xff0c;ytrue​ 是目标&#xff09;&#xff0c;定义逐点KL散度为&#xff1a; 为了在计算时避免下溢问题&#xff0c;此KLDivLoss期望输入在对数空间中。如果log_targetTrue&#xff0c;则目标…

【mediasoup-sfu-cpp】4: SfuDemo:join并发布视频创建RTCTransport流程分析

【mediasoup-sfu-cpp】3: SfuDemo:加入会议 有点卡,在本篇进行日志流程分析。demo\controller/RoomsController.hpp 创建router create() config.mediasoup.routerOptions++++++:OnSuccess D:\XTRANS\soup\mediasoup-sfu-cpp\demo\controller/RoomsController.hpp: Line 71: …

数据库高速缓存配置

数据库一般都配置数据高速缓存&#xff0c;并且可以高速缓存中按页大小分不同的缓冲池。 Oracle&#xff1a; db_cache_size是指db_block_size对应的缓冲池&#xff0c;也可以指定非db_block_size的缓冲池&#xff0c;一般也都会再配置一个32K的缓冲池&#xff0c;两个缓冲池加…

(CV)论文列表

CNN卷积神经网络之SKNet及代码 https://blog.csdn.net/qq_41917697/article/details/122791002 【CVPR2022 oral】MixFormer: Mixing Features across Windows and Dimensions 【精选】【CVPR2022 oral】MixFormer: Mixing Features across Windows and Dimensions-CSDN博客

软考考前提醒:准考证打印、注意事项!

一、准考证打印 打印时间&#xff1a;10月30日~11月3日 重要提醒&#xff1a;打印入口即将关闭&#xff0c;还没打印的朋友要抓紧时间&#xff0c;以免无法参加考试&#xff01;&#xff01;&#xff01; 准考证打印流程 登录中国计算机技术职业资格网&#xff0c;点击【报…

新一代构建工具Vite-xyphf

一、什么vite? vite:是一款思维比较前卫而且先进的构建工具,他解决了一些webpack解决不了的问题——在开发环境下可以实现按需编译&#xff0c;加快了开发速度。而在生产环境下&#xff0c;它使用Rollup进行打包&#xff0c;提供更好的tree-shaking、代码压缩和性能优化&…

grafana docker安装

grafana docker安装 Grafana是一款用Go语言开发的开源数据可视化工具&#xff0c;可以做数据监控和数据统计&#xff0c;带有告警功能。目前使用grafana的公司有很多&#xff0c;如paypal、ebay、intel等。 Grafana 是 Graphite 和 InfluxDB 仪表盘和图形编辑器。Grafana 是开…

基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v8.0版已发布

关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架&#xff0c;超轻量级、高度提炼&#xff0c;一套API优雅支持 UDP 、TCP 、WebSocket 三种协议&#xff0c;支持 iOS、Android、H5、标准Java、小程序、Uniapp&#xff0c;服务端基于Netty编写。 工程…

计算机网络-应用层

文章目录 应用层协议原理万维网和HTTP协议万维网概述统一资源定位符HTML文档 超文本传输协议&#xff08;HTTP&#xff09;HTTP报文格式请求报文响应报文cookie 万维网缓存与代理服务器 DNS系统域名空间域名服务器和资源记录域名解析过程递归查询迭代查询 动态主机配置协议&…

每日刷题_

前k个高频元素 347. 前 K 个高频元素 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 一共有三种不同的题解&#xff1a; 1、把数据存到哈希表中&#xff0c;然后通过哈希表来排序&#xff0c;时间复杂度…

SpringCloud Alibaba Demo(Nacos,OpenFeign,Gatway,Sentinel)

开源地址&#xff1a; ma/springcloud-alibaba-demo 简介 参考&#xff1a;https://www.cnblogs.com/zys2019/p/12682628.html SpringBoot、SpringCloud 、SpringCloud Alibaba 以及各种组件存在版本对应关系。可参考下面 版本对应 项目前期准备 启动nacos. ./startup.c…

数据结构(超详细讲解!!)第十八节 串(堆串)

1.定义 假设以一维数组heap &#xff3b;MAXSIZE&#xff3d; 表示可供字符串进行动态分配的存储空间&#xff0c;并设 int start 指向heap 中未分配区域的开始地址(初始化时start 0) 。在程序执行过程中&#xff0c;当生成一个新串时&#xff0c;就从start指示的位置起&#…

AQS 框架、JUC常见并发包 简述

AQS&#xff08;AbstractQueuedSynchronizer&#xff09;是 Java 中的一个强大的同步框架&#xff0c;为我们提供了实现各种同步器的基础。在本篇博客中&#xff0c;我们将介绍 AQS 框架的基本原理&#xff0c;并探讨几个常见的 AQS 实现&#xff1a;ReentrantLock、CountDownL…

kotlin中集合操作符

集合操作符 1.总数操作符 any —— 判断集合中 是否有满足条件 的元素&#xff1b; all —— 判断集合中的元素 是否都满足条件&#xff1b; none —— 判断集合中是否 都不满足条件&#xff0c;是则返回true&#xff1b; count —— 查询集合中 满足条件 的 元素个数&#x…

python科研绘图:条形图

条形图&#xff08;bar chart&#xff09;是一种以条形或柱状排列数据的图形表示形式&#xff0c;可以显示各项目之间的比较。它通常用于展示不同类别的数据&#xff0c;例如在分类问题中的不同类别、不同产品或不同年份的销售数据等。 条形图中的每个条形代表一个类别或一个数…

easyexcel根据模板导出Excel文件,表格自动填充问题

背景 同事在做easyexcel导出Excel&#xff0c;根据模板导出的时候&#xff0c;发现导出的表格&#xff0c;总会覆盖落款的内容。 这就很尴尬了&#xff0c;表格居然不能自动填充&#xff0c;直接怒喷工具&#xff0c;哈哈。 然后一起看了一下这个问题。 分析原因 我找了自…

MySQL - 系统库之 performance_schema

performance_schema &#xff1a;用于收集和存储关于数据库性能和资源利用情况的信息&#xff0c;可用于监控、分析和优化数据库的性能&#xff1a; 用途&#xff1a; 性能监控&#xff1a;performance_schema 用于监控数据库的性能。它提供了有关查询执行、锁等待、I/O操作、…

基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统

goframe-admin goframe-admin V1.0.0 平台简介 基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统。前端采用tdesign-vue-next-starter 、vue3、pinia、tdesign-vue-next。 特征 高生产率&#xff1a;几分钟即可搭建一个后台管理系统认证机制&#x…