将Bean信息封装到BeanDefinition对象然后放到Map中

news/2024/10/18 22:31:40/

文章目录

    • 1.目录
    • 2.MyScope.java 自定义的Scope注解枚举
    • 3.Scope.java 自定义Scope注解
    • 4.MonsterService.java 指定bean的作用域
    • 5.BeanDefintion.java bean的定义信息
    • 6.SunSpringApplicationContext.java Spring容器
    • 7.测试

1.目录

CleanShot 2024-08-05 at 14.08.13@2x

java_Scope_6">2.MyScope.java 自定义的Scope注解枚举

java">package com.sunxiansheng.sunspring.annotation.myenum;/*** Description: 自定义Scope注解,用于指定bean的作用域* @Author sun* @Create 2024/8/5 13:29* @Version 1.0*/
public enum MyScope {SINGLETON,PROTOTYPE;
}

java_Scope_26">3.Scope.java 自定义Scope注解

java">package com.sunxiansheng.sunspring.annotation;import com.sunxiansheng.sunspring.annotation.myenum.MyScope;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Description: 自定义Scope注解,用于指定bean的作用域* @Author sun* @Create 2024/8/5 13:28* @Version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {MyScope value() default MyScope.SINGLETON;}

java_bean_54">4.MonsterService.java 指定bean的作用域

java">package com.sunxiansheng.sunspring.compent;import com.sunxiansheng.sunspring.annotation.Component;
import com.sunxiansheng.sunspring.annotation.Scope;
import com.sunxiansheng.sunspring.annotation.myenum.MyScope;/*** Description: 怪物服务* @Author sun* @Create 2024/8/4 16:31* @Version 1.0*/
// 自定义注解:将MonsterService类交给自定义Spring容器管理
// 如果指定value属性,则使用value属性值作为bean的id,否则使用类名首字母小写作为bean的id
@Component
@Scope(value = MyScope.PROTOTYPE) // 指定bean的作用域为多例
public class MonsterService {
}

java_bean_77">5.BeanDefintion.java bean的定义信息

java">package com.sunxiansheng.sunspring.ioc;import com.sunxiansheng.sunspring.annotation.myenum.MyScope;/*** Description: Bean定义类,记录bean的信息* @Author sun* @Create 2024/8/5 13:41* @Version 1.0*/
public class BeanDefintion {// bean的作用域private MyScope scope;// bean的类型private Class<?> clazz;public MyScope getScope() {return scope;}public void setScope(MyScope scope) {this.scope = scope;}public Class<?> getClazz() {return clazz;}public void setClazz(Class<?> clazz) {this.clazz = clazz;}@Overridepublic String toString() {return "BeanDefintion{" +"scope='" + scope + '\'' +", clazz=" + clazz +'}';}}

java_Spring_125">6.SunSpringApplicationContext.java Spring容器

java">package com.sunxiansheng.sunspring.ioc;import com.sunxiansheng.sunspring.annotation.Component;
import com.sunxiansheng.sunspring.annotation.ComponentScan;
import com.sunxiansheng.sunspring.annotation.Scope;
import com.sunxiansheng.sunspring.annotation.myenum.MyScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;/*** Description: 自定义Spring容器* @Author sun* @Create 2024/8/4 16:35* @Version 1.0*/
public class SunSpringApplicationContext {private static final Logger log = LoggerFactory.getLogger(SunSpringApplicationContext.class);/*** bean定义的map*/private ConcurrentHashMap<String, BeanDefintion> beanDefintionMap = new ConcurrentHashMap<>();/*** 单例池*/private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();// 构造器,接收配置类的class对象public SunSpringApplicationContext(Class<?> configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {// 完成bean的扫描,将bean的信息记录到beanDefintionMap中beanDefinitionScan(configClass);}/*** 完成bean的扫描,将bean的信息记录到beanDefintionMap中* @param configClass* @throws ClassNotFoundException*/private void beanDefinitionScan(Class<?> configClass) throws ClassNotFoundException {// 传进来一个配置类的Class对象// 一、获取要扫描的包// 1.首先反射获取类的注解信息ComponentScan componentScan = configClass.getDeclaredAnnotation(ComponentScan.class);// 2.通过注解来获取要扫描的包的路径String path = componentScan.packagePath();log.info("要扫描的包路径为={}", path);// 二、得到要扫描包的.class文件对象,从而得到全路径进行反射// 1.获取App类加载器ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();// 2.获取要扫描包的真实路径,默认刚开始在根目录下path = path.replace(".", "/");URL resource = classLoader.getResource(path);// 3.由该路径创建一个文件对象,可使用resource.getFile()将URL类型转化为String类型File file = new File(resource.getFile());// 4.遍历该文件夹下的所有.class文件对象if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) {// 反射注入容器// 1.获取所有文件的绝对路径String absolutePath = f.getAbsolutePath();// 只处理class文件if (absolutePath.endsWith(".class")) {// 2.分割出类名String className = extractClassName(absolutePath);// 3.得到全路径String fullPath = path.replace("/", ".") + "." + className;// 4.判断是否需要注入容器,查看有没有自定义的注解ComponentClass<?> aClass = classLoader.loadClass(fullPath);// 如果该类使用了注解Component则说明是一个spring beanif (aClass.isAnnotationPresent(Component.class)) {log.info("这是一个Spring bean={}", aClass);// 将bean的信息记录到beanDefintionMap中BeanDefintion beanDefintion = new BeanDefintion();// 1.获取Scope注解的value值if (aClass.isAnnotationPresent(Scope.class)) {Scope scope = aClass.getDeclaredAnnotation(Scope.class);MyScope value = scope.value();// 放到beanDefintion中beanDefintion.setScope(value);} else {// 如果没有指定作用域,则默认为单例beanDefintion.setScope(MyScope.SINGLETON);}beanDefintion.setClazz(aClass);// 2.获取Component注解的value值Component component = aClass.getDeclaredAnnotation(Component.class);String beanName = component.value();if ("".equals(beanName)) {// 如果没有指定value属性,则使用类名首字母小写作为bean的idbeanName = className.substring(0, 1).toLowerCase() + className.substring(1);}// 3.将bean的id和bean的信息放到beanDefintionMap中beanDefintionMap.put(beanName, beanDefintion);// 打印bean的信息log.info("beanName={}, beanDefintion={}", beanName, beanDefintion);} else {log.info("这不是一个Spring bean={}", aClass);}}}}}// 返回容器中的对象public Object getBean(String name) {return null;}/*** 分割出类名* 类似于 com/sunxiansheng/sunspring/compent/MonsterService.class 的类名* @param filePath* @return*/private String extractClassName(String filePath) {// 获取最后一个 '/' 的位置int lastSlashIndex = filePath.lastIndexOf('/');// 获取最后一个 '.' 的位置int lastDotIndex = filePath.lastIndexOf('.');// 提取两者之间的字符串作为类名return filePath.substring(lastSlashIndex + 1, lastDotIndex);}}

7.测试

CleanShot 2024-08-05 at 14.10.38@2x


http://www.ppmy.cn/news/1514240.html

相关文章

vue.js的设计与实现(响应系统1)

文章目录 概要响应式数据与副作用函数响应式数据的基本实现设计一个完善的响应式系统小结 概要 响应系统式vue的重要组成部分&#xff0c;我们都知道vue3中采用了proxy实现响应式数据的&#xff0c;那是怎么实现的呢&#xff1f;我们往下看 响应式数据与副作用函数 大家肯定会…

gazebo下使用Fast-planner配置(包含mpc局部规划+控制Gazebo小车以及FastPlanner配置)

源码链接&#xff1a; https://github.com/USE-jx/NMPC_CASADI_CPP?tabreadme-ov-file #这是NMPC的 里面有Fast-Planner&#xff0c;但编译可能缺少东西&#xff0c;所以再放一个Fast-Planner的&#xff0c;可以装装缺少的库 https://github.com/HKUST-Aerial-Robotics/Fast-P…

YOLOv10:面向下一代目标检测模型的创新探索

随着计算机视觉技术的飞速发展&#xff0c;目标检测模型在各类应用场景中的重要性与日俱增。从自动驾驶到智能监控&#xff0c;目标检测的准确性和实时性都直接影响着应用的效果和用户体验。YOLO&#xff08;You Only Look Once&#xff09;系列作为实时目标检测的代表性模型&a…

Idea里配置Maven版本

一、安装Maven 1. 官网下载maven地址&#xff1a; Maven – Download Apache Maven Binary是可执行版本&#xff0c;已经编译好可以直接使用。 Source是源代码版本&#xff0c;需要自己编译成可执行软件才可使用。tar.gz和zip两种压缩格式,其实这两个压缩文件里面包含的内容是…

Google Play开发者账号地址验证难题?这些经验或许能帮到你

目前&#xff0c;想要把应用顺利上架到 Google Play&#xff0c;已经不像以前那么简单了&#xff0c;主要是开发者需要应对 Google 日益严格的审核机制。其中&#xff0c;账号验证的地址验证绝对是让很多人头疼的一个环节。 今天就来给大家分享一些真实的经验和干货&#xff0c…

解决ubuntu22.04无法识别CH340/CH341和vscode espidf插件无法选择串口设备节点问题

文章目录 解决ubuntu22.04无法识别CH340/CH341和vscode espidf插件无法选择串口设备节点问题不识别CH340/CH341报错解决办法升级驱动编译安装 卸载brltty程序 vscode espidf插件无法选择串口设备节点问题解决办法编译安装 解决ubuntu22.04无法识别CH340/CH341和vscode espidf插…

短视频SDK解决方案,高效集成,助力商业变现

美摄科技&#xff0c;作为业界领先的多媒体技术服务商&#xff0c;其全面升级的短视频SDK解决方案&#xff0c;旨在为开发者与内容创作者提供一站式、高效能的创作工具&#xff0c;让每一个灵感都能瞬间转化为触动人心的视频作品。 【一站式解决方案&#xff0c;重塑短视频创作…

Qt+ffmpeg环境搭建

Qtffmpeg环境搭建 各平台常见视频开发库举例: iOS&#xff1a;AVFoundation AudioUnitAndroid&#xff1a;MediaPlayer&#xff0c;MediaCodecWindows&#xff1a;DirectShowLinux&#xff1a;GStreamer FFmpeg 库是一个跨平台的视频开发库, 还有 libVLC 也是一个跨平台的视频开…