造个轮子-任务调度执行小框架-IOC容器实现

这篇具有很好参考价值的文章主要介绍了造个轮子-任务调度执行小框架-IOC容器实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

忙里偷闲,今天终于是把概率论这块骨头干下来了。所以的话,留了点时间,把整个项目的结构和基本的功能给实现以下。通过昨天的一个功能的一个设计,我想应该可以明白我想干啥吧。这里的话,重复一下,那就是俺们要搞一个任务执行框架。

使用场景

这个框架到底有啥用?举个简单的例子那就是,假设你要去超市买菜:为了方便买菜,你可以写一个购物清单,然后按照购物清单上面的每一个项,去购买东西。每一次写购物清单的时候,都要写上物品的名字,每次这样写实在是太麻烦了。不过,好在超市的商品有限,于是我们把这些商品都编上序号。于是下一次在书写购物清单的时候,只需要写上这个商品对应的编号就可以了,如果有特殊需求,只需要在商品序号上写上注释即可。同时有些常用的注释也有对应的序号,如果不是很特别的需求的话,直接写上这些注释序号就可以了。

那么在这个例子当中,指代的是啥呢,当你的一个任务,一个业务,需要执行多个方法的时候,你需要编写一个业务类这就相当于刚刚的例子当中去写清单一样。这个业务类里面写了很多调用那些方法的代码,你可能会写出这样的代码

功能方法代码
class A{
	A1(){};
	A2(){};
}

class B{
	B1(){};
	B2(){};
}

class C{
	C1(){};
	C2(){};
}

执行业务的方法(){
	B.B1();
	A.A2();
	C.C1();
}

当你的业务发生变更的时候你可能需要做出新的编排。当然这都不是最麻烦的,最麻烦的是,这些方法的执行可能有着不同的条件,于是接下来又进入了if-else时间。同时,有时候,我们还期望这些方法都能够执行成功,如果有一个方法执行失败,我们希望同时失败,并且恢复原来的状态,例如,你去超市买排骨炖玉米,清单上面有一堆佐料和排骨,如果排骨没有卖了,那么其他的也就没有必要购买了,这个时候买了的东西就要去退款,不要了。因此这样做代码就将显得臃肿,并且修改的代价较大。 那么为了解决这个问题,HTodoScheduling 小框架诞生啦~。

这里为啥是小框架呢,因为实现比较简陋,赶工嘛。所以实现会简单的,但是思想都是一样的,适合拿出来作为学习使用。

特性

这里的话,主要有如下特性:

  1. 清单异步执行
  2. 清单项同步执行
  3. 状态保存
  4. 状态恢复
  5. 定时失败任务重试

这里其实,比较核心的功能就这五个,接下来的小功能围绕这个展开即可。稍微敏感一点儿,你可能还发现了,这个状态保存和状态恢复,以及定时失败任务重试作用可不行哦~

项目结构

okey,我们先来查看一下我们的项目结构:
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
这里面的话,目前基本上是把整个项目需要用到的类,数据结构都定义好了。然后重点实现了一下这个IOC容器。因为接下来还需要解析到方法上面,所以要先把类解析出来。

那么在这里的话,和IOC容器相关的其实就这几个地方:

首先是我们的注解,这个的话,这几个注解啥意思,我估计应该不用我多说了,就是Spring的。当然在这个项目里面其实,依赖注入是不需要的,只是看起来不爽,加上去的。
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构

然后,干活的类就这几个:有啥用我们一一道来。
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构

初始化执行流程

okey,我们先来看看这个项目初始化执行的流程,当然这里的初始化流程是指当前的执行流程。因为后面的代码还没动,只是架子搭好了。

造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构

可替换核心组件

okey,我们先来看到我们的核心组件部分。目前你能够看到的其实就是这个:
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
这个是我们的配置解析,后面还有我们的日志,恢复等等,这里的话我们直接使用适配器设计模式。然后设计一个顶级接口:

package com.huterox.common;

public interface ConfigurationParse {

    void parseConfig();

}

然后有具体的实现:

package com.huterox.common.impl;


import com.huterox.config.Configuration;
import com.huterox.common.ConfigurationParse;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * 解析配置文件,这里目前还是解析这properties的文件
 * */

public class PropertiesConfigurationParse implements ConfigurationParse {

    private final Properties properties = new Properties();

    private void doLoadConfig(String contextproperties) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextproperties);
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void parseConfig() {
        //加载解析properties配置文件
        this.doLoadConfig(Configuration.configFileName);
        //解析完毕之后,获取对应的属性,然后把解析结果,放在Configuration当中
        String scanPackage = properties.getProperty("scanPackage");
        int schedulerSeconds = Integer.parseInt(properties.getProperty("schedulerSeconds"));
        Configuration.scanPackage = scanPackage;
        Configuration.schedulerSeconds = schedulerSeconds;
    }
}

在未来,你可以变成yaml,xml等等都可以,现在的话只是这个:

造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
那么这个时候的话,我们在这里有一个配置类:
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
那个解析器将解析到的值给到这里,别的地方就知道了。

之后就是俺们的替换部分。
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
看到这里,我们把要用的基本核心的组件放在这里,在需要的地方被调用。为了如果外部需要实现或者升级框架的话,那么只需要实现对应的接口,然后在这里覆盖原来的组件接口。当然后面这个玩意还会封装出一个接口,用户不是直接改这个玩意,这玩意是框架开发者使用的

容器创建

okey,前面的内容说完了,我们来说说这个,我们的容器创建。首先的话,我们其实是可以直接使用Spring的,但是这样做的话,扩展性就很差了,你必须依赖Spring,然鹅我压根用不到Spring全家桶的时候就很尴尬(当然估计现在很少这种场景了,苦笑)

扫描目标包

那么创建容器的话,当前第一步是扫描我们的目标包:

package com.huterox.core.suports;

import com.huterox.common.BeanNameConvert;
import com.huterox.common.ConfigurationParse;
import com.huterox.config.ConfigEngine;
import com.huterox.config.Configuration;
import com.huterox.core.beans.BeanDefinition;
import java.io.File;;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


/**
 * 扫描当前需要被放在容器当中的类
 * */
public class BeanDefinitionReader {

    private List<String> registryBeanClass = new ArrayList<>();
    
    public BeanDefinitionReader() {
        //初始化配置
        ConfigurationParse configurationParse = 
                (ConfigurationParse)ConfigEngine.corePart.get(ConfigurationParse.class);
        configurationParse.parseConfig();
        //初始化时,扫描目标包
        doScanner(Configuration.scanPackage);
        doLoadBeanDefinitions();
    }

    //负责读取配置文件
    public List<BeanDefinition> doLoadBeanDefinitions() {
        //这里注意此时我们存入的是类的包名com.xx.xx.xx
        List<BeanDefinition> result = new ArrayList<>();
        try {
            for (String className:registryBeanClass){
                Class<?> beanClass = Class.forName(className);
                if(beanClass.isInterface()) continue;
                result.add(doCreateBeanDefinition(BeanNameConvert.toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName()));
                //同时把对应的接口也扫描进去
                for(Class<?> InfClass:beanClass.getInterfaces()){
                    result.add(doCreateBeanDefinition(InfClass.getSimpleName(), beanClass.getName()));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    private BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setFactoryBeanName(factoryBeanName);
        beanDefinition.setBeanClassName(beanClassName);
        return beanDefinition;
    }
    
    private void doScanner(String scanPackage){
        // 扫描我们想要控制的那个包下面的所有类
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        assert url != null;
        File classDir = new File(url.getFile());
        for(File file: Objects.requireNonNull(classDir.listFiles())){
            if(file.isDirectory()){
                this.doScanner(scanPackage+"."+file.getName());
            }else {
                if (!file.getName().endsWith(".class")) continue;
                String clazzName = (scanPackage + "." + file.getName().replace(".class", ""));
                registryBeanClass.add(clazzName);
            }
        }
    }


}

这段代码的话主要就是,将我们的这个类扫描进去。同时存储到列表当中,这里面对类的信息进行了简单封装:

package com.huterox.core.beans;


/**
 * BeanDefinition 对目标类进行初步处理
 * */
public class BeanDefinition {

    //符合标准bean的名字
    private String factoryBeanName;
    //这个类的全路径
    private String beanClassName;

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
    }

    public String getFactoryBeanName() {
        return factoryBeanName;
    }

    public String getBeanClassName() {
        return beanClassName;
    }

}

当然这里还用到一个简单的工具类:

package com.huterox.common;


/**
 * 将Bean的名字进行转换,转化为符合Javabean标准的名字
 * */
public class BeanNameConvert {
    public static String toLowerFirstCase(String simpleName){
        //字母转换,符合javabean标准
        char[] chars = simpleName.toCharArray();
        if(67<=(int)chars[0]&&(int)chars[0]<=92)
            chars[0] +=32;
        return String.valueOf(chars);
    }
}

容器实例

okey,接下来创建我们的容器。
这里的话,主要有这几个步骤:

  1. 把我们刚刚扫描到的包存放到Map当中。注意,我们这里的实现,和Spring ScanComponent这个注解实现初始话容器有点像,但是和老八股的三级缓存,循环依赖的流程是不同的,在这里解决循环依赖用到是标记链(这个你待会就知道了,我自己取的名字)
  2. 初始化容器
  3. 注入依赖

BeanDefinitionMap 创建

造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构

    private void doRegistryBeanDefinition(List<BeanDefinition> beanDefinitions) throws Exception {

        for (BeanDefinition beanDefinition : beanDefinitions) {
            //双键存储便于双向查找,把bean的名字和对应的包名放在一起
            if (this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())) {
                throw new Exception("The " + beanDefinition.getFactoryBeanName() + " is exists!");
            }
            this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
            this.beanDefinitionMap.put(beanDefinition.getBeanClassName(), beanDefinition);
        }
    }

这个代码没啥,就是把先前扫描到的玩意放在Map当中,其实也是做个检测,看看有没有重复的类名。

过滤并初始化创建对象

之后的话,我们去遍历这个Map,然后创建对象:
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构
然后在这里面调用:
造个轮子-任务调度执行小框架-IOC容器实现,手把手教你编写任务执行框架,java,spring,架构

之后在这里进行基本过滤:

    /**
     * 把打了TodoComponent,TodoService,TodoService的类放在我们的容器里面
     * 并且这里进行无参构造,也就是初步实例化
     * 后面我们再把这些玩意的方法进行解析
    * */
    private Object instanceBean(String beanName, BeanDefinition beanDefinition) {

        String className = beanDefinition.getBeanClassName();
        Object instance = null;
        try {
            Class<?> clazz = Class.forName(className);
            if (!(clazz.isAnnotationPresent(TodoComponent.class) ||
                    clazz.isAnnotationPresent(TodoService.class)) ||
                    clazz.isAnnotationPresent(TodoService.class)
            ) {
                return null;
            }
            //先进行初步得无参构造,然后放到这个factoryBeanObjectCache当中去
            instance = clazz.newInstance();
            this.factoryBeanObjectCache.put(beanName, instance);

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return instance;
    }

这个时候的话,我们只是初始化构建,还没有注入依赖。factoryBeanObjectCache 只是一个Cache,因为后面有一个获取全部对象的方法。

依赖注入

接下来我们进行依赖注入。这个时候的话,参与到我们真正的容器创建,目前是有这两个家伙:

    private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private final Map<String, BeanWrapper> factoryBeanInstanceCache = new HashMap<>();

在处理循环依赖的时候,使用到这个:

    //记录一下谁依赖了谁,在创建过程当中,还没有被创建的话,表示:B被A依赖,但是此时B没有完成实例
    private final Map<String, List<String>> factoryBeanPopulateCache = new HashMap<>();

这里的话,和Spring老八股当中的循环依赖的那个解决方案是不同的,那个老八股里面的其实是懒实例,按需注入的时候才那样处理的,有历史遗留问题,当然还有就是,我们这个比较简单,一开始就是全加载,人家还有懒加载。

    //创建Bean的实例
    public Object getBean(String beanName) {
        //得到对象的全包名,当然这个信息封装在beanDefinition里面
        BeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName);
        //实例化,这个的话是先进行基本地无参构造实例化对象,此时是半成品
        Object instance = instanceBean(beanName, beanDefinition);
        if (instance == null) return null;
        //实例封装为beanWrapper当中
        BeanWrapper beanWrapper = new BeanWrapper(instance);
        //将这个wrapper对象放在IOC容器里面,允许提取暴露
        this.factoryBeanInstanceCache.put(beanName, beanWrapper);
        //完成依赖注入
        populateBean(beanWrapper);
        return this.factoryBeanInstanceCache.get(beanName).getWrapperInstance();
    }

然后我们的核心代码在这儿:

    private void populateBean(BeanWrapper beanWrapper){
        //开始做依赖注入给值
        Object instance = beanWrapper.getWrapperInstance();
        Class<?> clazz = beanWrapper.getWrapperClass();
        Field[] fields = clazz.getDeclaredFields();
        String beanName = BeanNameConvert.toLowerFirstCase(clazz.getSimpleName());
        //遍历所有的字段,看看有木有需要依赖注入的
        for (Field field : fields) {
            if (!(field.isAnnotationPresent(TodoAutowired.class))) continue;
            TodoAutowired autowired = field.getAnnotation(TodoAutowired.class);
            String autowiredBeanName = autowired.value().trim();
            if ("".equals(autowiredBeanName)) {
                autowiredBeanName = field.getType().getName();
            }
            //打开权限
            field.setAccessible(true);
            try {
                if (!this.factoryBeanInstanceCache.containsKey(autowiredBeanName)){
                    //说明现在这个容器当中,依赖的那个家伙还没有实例化
                    if(this.factoryBeanPopulateCache.containsKey(autowiredBeanName)){
                        List<String> needings = this.factoryBeanPopulateCache.get(autowiredBeanName);
                        needings.add(beanName);
                    }else {
                        List<String> needings = new ArrayList<>();
                        needings.add(beanName);
                        this.factoryBeanPopulateCache.put(autowiredBeanName,needings);
                    }
                    continue;
                }
                //这个就是为什么要按照标准来写首字母要小写
                field.set(instance, this.factoryBeanInstanceCache.get(autowiredBeanName).getWrapperInstance());

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //顺便检测当前的bean有没有在创建之前被依赖的情况,有的话补偿一下
        if(this.factoryBeanPopulateCache.containsKey(beanName)){
            for (String populateBeanName:this.factoryBeanPopulateCache.get(beanName)){
                Object instanceNeed = this.factoryBeanInstanceCache.get(populateBeanName).getWrapperInstance();
                Class<?> clazzNeed = this.factoryBeanInstanceCache.get(populateBeanName).getWrapperClass();
                try {
                    Field declaredField = clazzNeed.getDeclaredField(beanName);
                    declaredField.setAccessible(true);
                    declaredField.set(instanceNeed,instance);
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

    }

这样以来的话,就完成了简单的IOC容器实例化处理。之后的话,在我们这边拿到这个容器,然后的话,后面就是解析它的方法,完成清单创建,等等工作就好了。

完整代码

ok,我们来看到最终实现的完整代码:文章来源地址https://www.toymoban.com/news/detail-637572.html

package com.huterox.core.suports;

import com.huterox.annotate.TodoAutowired;
import com.huterox.annotate.TodoComponent;
import com.huterox.annotate.TodoService;
import com.huterox.common.BeanNameConvert;
import com.huterox.core.beans.BeanDefinition;
import com.huterox.core.wapper.BeanWrapper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TodoApplicationContext {

    private BeanDefinitionReader reader;
    private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private final Map<String, BeanWrapper> factoryBeanInstanceCache = new HashMap<>();
    private final Map<String, Object> factoryBeanObjectCache = new HashMap<>();
    //记录一下谁依赖了谁,在创建过程当中,还没有被创建的话,表示:B被A依赖,但是此时B没有完成实例
    private final Map<String, List<String>> factoryBeanPopulateCache = new HashMap<>();

    public TodoApplicationContext() {

        //加载配置文件读取器
        this.reader = new BeanDefinitionReader();
        List<BeanDefinition> beanDefinitions = this.reader.doLoadBeanDefinitions();
        //2.缓存beanDefinitions对象
        try {
            doRegistryBeanDefinition(beanDefinitions);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.创建IOC容器,把类都放在IOC容器里面
        doCreateBean();
    }

    private void doCreateBean() {
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : this.beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            //非延时加载
            getBean(beanName);
        }
    }

    private void doRegistryBeanDefinition(List<BeanDefinition> beanDefinitions) throws Exception {

        for (BeanDefinition beanDefinition : beanDefinitions) {
            //双键存储便于双向查找,把bean的名字和对应的包名放在一起
            if (this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())) {
                throw new Exception("The " + beanDefinition.getFactoryBeanName() + " is exists!");
            }
            this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
            this.beanDefinitionMap.put(beanDefinition.getBeanClassName(), beanDefinition);
        }
    }

    //创建Bean的实例
    public Object getBean(String beanName) {
        //得到对象的全包名,当然这个信息封装在beanDefinition里面
        BeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName);
        //实例化,这个的话是先进行基本地无参构造实例化对象,此时是半成品
        Object instance = instanceBean(beanName, beanDefinition);
        if (instance == null) return null;
        //实例封装为beanWrapper当中
        BeanWrapper beanWrapper = new BeanWrapper(instance);
        //将这个wrapper对象放在IOC容器里面,允许提取暴露
        this.factoryBeanInstanceCache.put(beanName, beanWrapper);
        //完成依赖注入
        populateBean(beanWrapper);
        return this.factoryBeanInstanceCache.get(beanName).getWrapperInstance();
    }

    private void populateBean(BeanWrapper beanWrapper){
        //开始做依赖注入给值
        Object instance = beanWrapper.getWrapperInstance();
        Class<?> clazz = beanWrapper.getWrapperClass();
        Field[] fields = clazz.getDeclaredFields();
        String beanName = BeanNameConvert.toLowerFirstCase(clazz.getSimpleName());
        //遍历所有的字段,看看有木有需要依赖注入的
        for (Field field : fields) {
            if (!(field.isAnnotationPresent(TodoAutowired.class))) continue;
            TodoAutowired autowired = field.getAnnotation(TodoAutowired.class);
            String autowiredBeanName = autowired.value().trim();
            if ("".equals(autowiredBeanName)) {
                autowiredBeanName = field.getType().getName();
            }
            //打开权限
            field.setAccessible(true);
            try {
                if (!this.factoryBeanInstanceCache.containsKey(autowiredBeanName)){
                    //说明现在这个容器当中,依赖的那个家伙还没有实例化
                    if(this.factoryBeanPopulateCache.containsKey(autowiredBeanName)){
                        List<String> needings = this.factoryBeanPopulateCache.get(autowiredBeanName);
                        needings.add(beanName);
                    }else {
                        List<String> needings = new ArrayList<>();
                        needings.add(beanName);
                        this.factoryBeanPopulateCache.put(autowiredBeanName,needings);
                    }
                    continue;
                }
                //这个就是为什么要按照标准来写首字母要小写
                field.set(instance, this.factoryBeanInstanceCache.get(autowiredBeanName).getWrapperInstance());

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //顺便检测当前的bean有没有在创建之前被依赖的情况,有的话补偿一下
        if(this.factoryBeanPopulateCache.containsKey(beanName)){
            for (String populateBeanName:this.factoryBeanPopulateCache.get(beanName)){
                Object instanceNeed = this.factoryBeanInstanceCache.get(populateBeanName).getWrapperInstance();
                Class<?> clazzNeed = this.factoryBeanInstanceCache.get(populateBeanName).getWrapperClass();
                try {
                    Field declaredField = clazzNeed.getDeclaredField(beanName);
                    declaredField.setAccessible(true);
                    declaredField.set(instanceNeed,instance);
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 把打了TodoComponent,TodoService,TodoService的类放在我们的容器里面
     * 并且这里进行无参构造,也就是初步实例化
     * 后面我们再把这些玩意的方法进行解析
    * */
    private Object instanceBean(String beanName, BeanDefinition beanDefinition) {

        String className = beanDefinition.getBeanClassName();
        Object instance = null;
        try {
            Class<?> clazz = Class.forName(className);
            if (!(clazz.isAnnotationPresent(TodoComponent.class) ||
                    clazz.isAnnotationPresent(TodoService.class)) ||
                    clazz.isAnnotationPresent(TodoService.class)
            ) {
                return null;
            }
            //先进行初步得无参构造,然后放到这个factoryBeanObjectCache当中去
            instance = clazz.newInstance();
            this.factoryBeanObjectCache.put(beanName, instance);

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return instance;
    }

    //重载按照这个类的类型来创建
    public Object getBean(Class<?> className) {
        return getBean(className.getName());
    }

    public int getBeanDefinitionCount() {
        return this.beanDefinitionMap.size();
    }

    public String[] getBeanDefinitionNames() {
        return this.beanDefinitionMap.keySet().toArray(new String[0]);
    }

    public BeanDefinitionReader getReader() {
        return reader;
    }

    public void setReader(BeanDefinitionReader reader) {
        this.reader = reader;
    }

    public Map<String, BeanDefinition> getBeanDefinitionMap() {
        return beanDefinitionMap;
    }

    public Map<String, BeanWrapper> getFactoryBeanInstanceCache() {
        return factoryBeanInstanceCache;
    }

    public Map<String, Object> getFactoryBeanObjectCache() {
        return factoryBeanObjectCache;
    }
}

到了这里,关于造个轮子-任务调度执行小框架-IOC容器实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring Boot 3 整合 xxl-job 实现分布式定时任务调度,结合 Docker 容器化部署(图文指南)

    Spring Boot 3 整合 xxl-job 实现分布式定时任务调度,结合 Docker 容器化部署(图文指南)

    xxl-job 是一个分布式任务调度平台,它提供了强大的任务调度和执行能力,可以帮助我们实现任务的自动化调度和执行。本文将介绍如何在 Docker 环境下部署 xxl-job,并将其与 Spring Boot 进行整合。 数据库脚本:tables_xxl_job-2.4.0.sql Docker 镜像地址: https://hub.docker.com/r/xuxueli/xxl-jo

    2024年02月06日
    浏览(22)
  • 【后端-Quartz】Springboot整合Quartz支持集群环境-设计业务与框架分离及实现定时任务调度

    【后端-Quartz】Springboot整合Quartz支持集群环境-设计业务与框架分离及实现定时任务调度

    我们的各个服务需要改造支持集群,现在的授权、日程使用的是基于内存的spring scheduler定时任务,如果部署多个节点,那么到了时间点,多个节点都会开始执行定时任务从而可能引起业务和性能上的问题。 服务中的定时任务比较轻量,为了避免引入redis、zookeeper、单独的定时

    2023年04月09日
    浏览(13)
  • 【框架源码】手写Spring框架IOC容器核心流程

    【框架源码】手写Spring框架IOC容器核心流程

    要是想要了解Spring IOC底层,首先我们就得先了解什么是IOC。 IOC就是控制反转,把对象创建和对象之间的调用过程交给Spring进行管理。 使用IOC目的就是之前我们创建对象的方式都是用new的方式创建,这个方式有个缺点,被创建对象的类的位置一旦被改动,new就会报错,类与类

    2024年02月06日
    浏览(14)
  • Spring框架IOC容器和DI依赖注入

    IOC(Invertion Of Control):控制反转,使用对象时,由使用new创建对象转变为由外部提供对象,此过程中对象的创建控制权由程序转移到外部的思想称之为控制反转. DI(Dependency Injection):依赖注入,在容器中建立bean与bean之间的关系的过程,称之为依赖注入 pom.xml依赖引入 BookDao BookDaoImpl Book

    2023年04月09日
    浏览(18)
  • linux-crontab每分钟定时执行/定时任务调度

    linux-crontab每分钟定时执行/定时任务调度

    本文讲解linux上如何调用定时任务,如每分钟打印日志,每日24点执行日志切割脚本等等。 在Linux系统中,crontab命令是一个用于执行定时任务的命令, crond(crontab)是系统默认自带的定时服务 。我们可以通过编辑crontab文件来设置定时任务,使系统可以自动按照设定的时间和频率

    2024年02月06日
    浏览(15)
  • XXL-JOB 任务调度中心 后台任意命令执行漏洞

    XXL-JOB 任务调度中心 后台任意命令执行漏洞

    在日常开发中,经常会用定时任务执行某些不紧急又非常重要的事情,例如批量结算,计算当日的订单量,当日的成本收入等。当存在大量定时任务的时候,任务的管理也会成为一个比较头痛的问题。xxl-job,就是一个比较成熟的分布式任务调度平台。XXL-JOB 任务调度中心系统

    2024年02月08日
    浏览(11)
  • 分布式定时任务调度框架Quartz

    分布式定时任务调度框架Quartz

    Quartz是一个定时任务调度框架,比如你遇到这样的问题: 比如淘宝的待支付功能,后台会在你生成订单后24小时后,查看订单是否支付,未支付则取消订单 比如vip的每月自动续费功能 … 想定时在某个时间,去做某件事 Quartz是一套轻量级的任务调度框架,只需要定义了 Job(

    2024年02月04日
    浏览(15)
  • .net下优秀的IOC容器框架Autofac的使用方法,实例解析

    .net下优秀的IOC容器框架Autofac的使用方法,实例解析

    Autofac是一个功能强大的依赖注入容器,它提供了一种简单和灵活的方式来管理对象之间的依赖关系。下面是Autofac的一些优点: 简单易用:Autofac提供了一种直观和简洁的方式来注册和解析依赖项。它的API设计得非常易于理解和使用,使得开发人员可以轻松地配置和管理依赖关

    2024年02月05日
    浏览(7)
  • 【开源项目】任务调度框架PowerJob介绍及源码解析

    【开源项目】任务调度框架PowerJob介绍及源码解析

    PowerJob(原OhMyScheduler)是全新一代分布式调度与计算框架,能让您轻松完成作业的调度与繁杂任务的分布式计算。 源码:https://gitee.com/KFCFans/PowerJob 官网:http://www.powerjob.tech/index.html https://www.yuque.com/powerjob/guidence/nyio9g 服务端启动 PowerJobServerApplication 启动。 AkkaStarter.init(); ,

    2023年04月16日
    浏览(8)
  • 分布式任务调度框架Power-Job

    分布式任务调度框架Power-Job

    在大型业务业务系统中,不可避免会出现一些需要定时执行需求的场景,例如定时同步数据,定时清洗数据,定时生成报表,大量机器一同执行某个任务,甚至有些需要分布式处理的任务例如需要更新一大批数据,单机耗时太长需要进行任务分发,利用集群的计算能力等等

    2024年02月04日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包