首页 > 编程语言 >接口编程

接口编程

时间:2023-09-18 11:11:28浏览次数:55  
标签:aClass String 编程 System 接口 println class out

接口编程

在创建好 Bean 实例后,判断是否要初始化,心得:

  • 容器中常用的方法是:根据该类是否实现了某个接口,来判断是否要执行某个业务逻辑
  • 这其实就是 java基础的 接口编程的 实际运用
package com.llq.spring.ioc;

/**
 * Spring 原生 Ioc 容器
 */
public class LlqSpringApplicationContext {
    //  定义属性 BeanDefinitionMap,用于存放 BeanDefinition
    private ConcurrentHashMap<String, BeanDefinition> BeanDefinitionMap = new ConcurrentHashMap<>();
    //  定义属性 singletonObjects,作为单例池
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    private Class configClass;

    public LlqSpringApplicationContext(Class configClass) {
        BeanDefinitionsScan(configClass);
    }

    public ConcurrentHashMap<String, BeanDefinition> getBeanDefinitionMap() {
        return BeanDefinitionMap;
    }

    public ConcurrentHashMap<String, Object> getSingletonObjects() {
        return singletonObjects;
    }

    public void BeanDefinitionsScan(Class configClass) {
        //  这里拿到了自定义配置类的 Class 类型
        this.configClass = configClass;
        System.out.println("配置类的 Class 类型");
        System.out.println("this.configClass= " + this.configClass);
        //  1. 先得到 LlqSpringConfig 配置的注解 @ComponentScan(value = "com.llq.spring.component")
        ComponentScan declaredAnnotation = (ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);
        //  2. 通过 ComponentScan的 value ===> 要扫描的包
        String path = declaredAnnotation.value();
        System.out.println("待扫描的包如下:");
        System.out.println(path);   //  com.llq.spring.component ===> 路径的话,要将 . 替换为 、 ===》com/llq/spring/component
        String scanDir = path.replace(".", "/");
        System.out.println(scanDir);

        //  3. 得到扫描包下的所有资源(类.class) ===> 工作目录的 class
        URL resource = configClass.getClassLoader().getResource(scanDir);  //  URL 对象有许多 API
        scanDir = resource.getPath();
        System.out.println("我们真正要扫描的路径如下:");
        System.out.println(scanDir);

        //  4. 将要加载的资源(.class) 路径下的文件进行遍历 ===> IO 知识

        File file = new File(scanDir); //  得到目录
        File[] files = file.listFiles();    //  列出目录下的所有文件

        System.out.println("==============");
        for (File f : files) {
            String absolutePath = f.getAbsolutePath();
            //  注意这里,只处理 .class 文件
            if (absolutePath.endsWith(".class")) {

                System.out.println(absolutePath);   //  D:\spring5\out\production\spring5\com\llq\spring\component\UserService.class
                //  现在反射需要得到:com.llq.spring.component.UserService
                //  1. 先获取类名
                String[] split = absolutePath.split("\\\\");
                String s = split[split.length - 1];
                System.out.println(s);
                String className = split[split.length - 1].split("\\.")[0];
                //  得到类名
                System.out.println("类名:" + className);
                //  再将 / 改回成 .
                String classFullName = path + "." + className; // 包名 + 类名
                System.out.println(classFullName);

                //  2. 判断该类是否需要注入到容器中
                //      观察该类是否包含以下注解
                //      @Component、@Service、@Repository、@Controller
                try {
                    Class<?> aClass = Class.forName(classFullName);
                    if (aClass.isAnnotationPresent(Component.class)) {
                        //  如果该类使用了 @Component 注解,说明是 Spring Bean
                        System.out.println("这是一个 Spring Bean= " + aClass + " 类名 " + className);
                        //  1. 先得到 beanName
                        String beanName = "";
                        String value = aClass.getDeclaredAnnotation(Component.class).value();
                        if ("".equals(value)) { //  是否右 scope 注解
                            className = className.substring(0, 1).toLowerCase() + className.substring(1);   //  首字母小写
                            beanName = className;
                        } else {
                            beanName = value;
                        }
                        System.out.println("key:" + beanName);

                        String scopeValue = "";
                        //  将 Bean信息封装到 BeanDefinition 对象 ===> 放入到 BeanDefinitionMap中
                        Scope scope = aClass.getDeclaredAnnotation(Scope.class);
                        if (scope == null) {
                            scopeValue = "singleton";
                        } else {
                            scopeValue = scope.value();
                        }

                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setaClass(aClass);
                        beanDefinition.setScope(scopeValue);
                        BeanDefinitionMap.put(beanName, beanDefinition);

                        //  初始化单例池
                        if ("singleton".equals(scopeValue)) {
                            //  已经创建好 Bean 对象了,还要判断是否要执行 初始化方法
                            System.out.println("我是单例,直接实例化,放入到单例池 singletonObjects 中");
                            Object o = aClass.getConstructor().newInstance();
                            if (o instanceof InitializingBean){
                                ((InitializingBean) o).afterPropertiesSet();
                            }
                            singletonObjects.put(beanName, o);
                        }
                        System.out.println("---------------------------");

                    } else {
                        System.out.println("这不是一个 Spring Bean" + " 类名 " + className);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Object createBean(BeanDefinition beanDefinition){
        Object o = null;
        Class aClass = beanDefinition.getaClass();
        Field[] declaredFields = aClass.getDeclaredFields();    //  拿到所有字段

        try {
            o = aClass.getConstructor().newInstance();

            for (Field declaredField : declaredFields) {
                if (declaredField.getAnnotation(Autowired.class) != null){  // 字段上是否有 @Autowired 注解
                    //  1. 先看单例池中有没有,有的话直接 get
                    //  2. 没有的话,new 一个 新的
                    String name = declaredField.getName();
                    Object bean = getBean(name);    //  待注入的依赖
                    declaredField.setAccessible(true);
                    declaredField.set(o, bean);
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        System.out.println("创建好 Bean 实例 " + o);
        //  这里判断是否执行 Bean 初始化方法
        //  1. 判断当前创建的 Bean 对象是否实现了 InitializingBean 接口
        if (o instanceof InitializingBean){
            try {
                ((InitializingBean) o).afterPropertiesSet();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return o;
    }

    public Object getBean(String name){
        if (singletonObjects.containsKey(name)){   //  单例池中有的话
            return singletonObjects.get(name);
        }

        Object o = null;

        if (BeanDefinitionMap.containsKey(name) && "prototype".equals(BeanDefinitionMap.get(name).getScope())){
            o = createBean(BeanDefinitionMap.get(name));
        }

        if (o == null){
            throw new NullPointerException("没有该 Bean");
        }
        return o;
    }
}

标签:aClass,String,编程,System,接口,println,class,out
From: https://www.cnblogs.com/aclq/p/17711359.html

相关文章

  • Java实现接口
    声明:本文记录基于JDK8(8u211)的继承使用规则如果存在错误,请发邮件至[email protected]联系我创作时间:2023-09-1511:00:21创作情况:失业第45天,地处成都金牛区创作者:一口吃不成胖子接口就是一种规范,对实现他的类进行限制,它本身并不实现任何方法,接口中不能声明具体实现的方......
  • 硬盘接口 最高速度
    在PCI-E3.0模式下,NVMeM.2固态盘的最高速度是3500MB/s。在PCI-E4.0模式下,NVMeM.2固态盘的最高速度是6700MB/s。从理论数据来看,PCI-E5.0的带宽相比PCI-E4.0翻了一倍,达到了1600MT/s。它的理论读取速度最高能够达到14GB/s,写入速度可以达到9GB/s,几乎是PCI-E4.0的两倍。SATA1......
  • 最新USB3.2接口,速度每秒传输2GB
    你还用U盘吗?根据最新的USB结构规范来看,你的U盘或许该换新了。USBPromoterGroup近日宣布USB3.2规格将让现有的USBType-C数据线传输速度提升一倍:作为USB3.1的升级版,它最主要的改变就是将理论传输速率从1GB/s提升到2GB/ 根据公布的细节显示,USBType-C线缆已经支持多通道操作,......
  • SK 简化流行编程语言对 生成式AI 应用开发的支持
    SemanticKernel[1]是一个将大型语言模型(LLM)与流行的编程语言相结合的SDK。Microsoft将SemanticKernel(简称SK)称为轻量级SDK,支持AILLM的集成。Microsoft今年3月份时候首次开源了SK,SK不仅支持C#、还支持Java和Python编程语言。生成式AI应用开发所带来新的语义编程,国际组织世......
  • TienChin 渠道管理-更新渠道接口开发
    ChannelController/***修改渠道*/@PreAuthorize("hasPermission('tienchin:channel:edit')")@Log(title="渠道管理",businessType=BusinessType.UPDATE)@PutMappingAjaxResultedit(@Validated@RequestBodyChannelVOchannelVO){......
  • 第一次个人编程项目
    这个作业属于哪个课程计科21级12班这个作业要求在哪里个人项目这个作业的目标熟悉个人软件开发流程gitee:https://gitee.com/jiajidong/3121004864/tree/master/1.PSP表格PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗时(分钟)Planni......
  • Rockchip RK3399 - USB触摸屏接口驱动
    ----------------------------------------------------------------------------------------------------------------------------开发板:NanoPC-T4开发板eMMC:16GBLPDDR3:4GB显示屏:15.6英寸HDMI接口显示屏u-boot:2023.04linux:6.3----------------------------------......
  • 33. 数据库编程
    一、数据库编程接口  程序运行的时候,数据都是在内存中的。当程序终止的时候,通常都需要将数据保存到磁盘上。为了便于程序保存的读取数据,并能直接通过条件查询跨快速查询指定的数据,就出现了数据库(Database)这种专门用于集中存储和查询的软件。  在Python中提供了数据库连接......
  • 《Java编程思想第四版》学习笔记28--关于StreamTokenizer
    //:SortedWordCount.java//Countswordsinafile,outputs//resultsinsortedform.importjava.io.*;importjava.util.*;importc08.*;//ContainsStrSortVectorclassCounter{privateinti=1;intread(){returni;}voidincrement(){i++;}}pu......
  • 利用SharedArrayBuffer进行多线程编程
    利用SharedArrayBuffer进行多线程编程在现代Web应用程序中,性能是一个至关重要的因素。为了提高Web应用程序的性能,我们经常需要执行并行计算,例如图像处理、音频处理或数据分析。在这种情况下,多线程编程是一种强大的工具,它允许我们充分利用多核处理器。然而,多线程编程并不是一件容易......