克山县名欧服务器有限公司

新闻动态你的位置:克山县名欧服务器有限公司 > 新闻动态 > 同期界说了类加载器的卸载方法

同期界说了类加载器的卸载方法

发布日期:2024-07-03 15:20    点击次数:73

同期界说了类加载器的卸载方法

温州高能电气有限公司 一、详细1、布景

现在数据搞定处事中有广阔搞定任务,当其中任一搞定任务有改革需要升级或新增一个搞定任务时,都需要将数据搞定处事重启,会影响其他搞定任务的平方初始。

2、缱绻或者动态启动、住手任一搞定任务或者动态升级、添加搞定任务启动、住手搞定任务或升级、添加搞定任务不成影响其他任务3、决议为了相沿业务代码尽量的解耦,把部分业务功能通过动态加载的步地加载到主重要中,以高傲可插拔式的加载、组合式的部署。联结xxl-job任务攻击框架,将数据搞定任务作念成xxl-job任务的步地注册到xxl-job中,浅近颐养经管。二、动态加载1、自界说类加载器

URLClassLoader 是一种稀奇的类加载器,不错从指定的 URL 中加载类和资源。它的主要作用是动态加载外部的 JAR 包或者类文献,从而杀青动态彭胀哄骗重要的功。为了便于经管动态加载的jar包,自界说类加载器领受URLClassloader。

平乐县达大棉类有限公司 53); font-size: 16px; letter-spacing: 0.8px; text-align: left; word-spacing: 0.8px; background-color: rgb(255,平乐县达大棉类有限公司 255, 255); border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">/** * 自界说类加载器 * * @author lijianyu * @date 2023/04/03 17:54 **/public class MyClassLoader extends URLClassLoader {    private Map<String, Class<?>> loadedClasses = new ConcurrentHashMap<>();    public Map<String, Class<?>> getLoadedClasses() {        return loadedClasses;    }    public MyClassLoader(URL[] urls, ClassLoader parent) {        super(urls, parent);    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        // 从已加载的类皆麇集得到指命称号的类        Class<?> clazz = loadedClasses.get(name);        if (clazz != null) {            return clazz;        }        try {            // 调用父类的findClass方法加载指命称号的类            clazz = super.findClass(name);            // 将加载的类添加到已加载的类皆麇集            loadedClasses.put(name, clazz);            return clazz;        } catch (ClassNotFoundException e) {            e.printStackTrace();            return null;        }    }    public void unload() {        try {            for (Map.Entry<String, Class<?>> entry : loadedClasses.entrySet()) {                // 从已加载的类皆麇集移除该类                String className = entry.getKey();                loadedClasses.remove(className);                try{                    // 调用该类的destory方法,回收资源                    Class<?> clazz = entry.getValue();                    Method destory = clazz.getDeclaredMethod("destory");                    destory.invoke(clazz);                } catch (Exception e ) {                    // 标明该类莫得destory方法                }            }            // 从其父类加载器的加载器脉络结构中移除该类加载器            close();        } catch (Exception e) {            e.printStackTrace();        }    }}
自界说类加载器中,为了浅近类的卸载,界说一个map保存已加载的类信息。key为这个类的ClassName,value为这个类的类信息。同期界说了类加载器的卸载方法,卸载方法中,将已加载的类的皆麇集移除该类。由于此类可能使用系统资源或调用线程,为了幸免资源未回收引起的内存溢出,通过反射调用这个类中的destroy方法,回收资源。终末调用close方法。2、动态加载

广电 53); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-size: 16px; text-align: left; text-indent: 0em; text-wrap: wrap; word-spacing: 0.8px; background-color: rgb(255, 255, 255); line-height: 1.75; letter-spacing: 0em;">由于此面貌使用spring框架,以及xxl-job任务的机制调用动态加载的代码,因此要完成以下内容

将动态加载的jar包读到内存中将有spring注解的类,通过注解扫描的步地,扫描并手动添加到spring容器中。将@XxlJob注解的方法,通过注解扫描的步地,手动添加到xxljob本质器中。
/** * @author lijianyu * @date 2023/04/29 13:18 **/@Componentpublic class DynamicLoad {    private static Logger logger = LoggerFactory.getLogger(DynamicLoad.class);    @Autowired    private ApplicationContext applicationContext;    private Map<String, MyClassLoader> myClassLoaderCenter = new ConcurrentHashMap<>();    @Value("${dynamicLoad.path}")    private String path;    /**     * 动态加载指定旅途下指定jar包     * @param path     * @param fileName     * @param isRegistXxlJob  是否需要注册xxljob本质器,面貌初度启动不需要注册本质器     * @return map<jobHander, Cron> 创建xxljob任务时需要的参数设立     */    public void loadJar(String path, String fileName, Boolean isRegistXxlJob) throws ClassNotFoundException, InstantiationException, IllegalAccessException {        File file = new File(path +"/" + fileName);        Map<String, String> jobPar = new HashMap<>();        // 得到beanFactory        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();        // 得到面前面貌的本质器        try {            // URLClassloader加载jar包方法必须这样写            URL url = new URL("jar:file:" + file.getAbsolutePath() + "!/");            URLConnection urlConnection = url.openConnection();            JarURLConnection jarURLConnection = (JarURLConnection)urlConnection;            // 得到jar文献            JarFile jarFile = jarURLConnection.getJarFile();            Enumeration<JarEntry> entries = jarFile.entries();            // 创建自界说类加载器,并加到map中浅近经管            MyClassLoader myClassloader = new MyClassLoader(new URL[] { url }, ClassLoader.getSystemClassLoader());            myClassLoaderCenter.put(fileName, myClassloader);            Set<Class> initBeanClass = new HashSet<>(jarFile.size());            // 遍历文献            while (entries.hasMoreElements()) {                JarEntry jarEntry = entries.nextElement();                if (jarEntry.getName().endsWith(".class")) {                    // 1. 加载类到jvm中                    // 得到类的全旅途名                    String className = jarEntry.getName().replace('/', '.').substring(0, jarEntry.getName().length() - 6);                    // 1.1进行反射得到                    myClassloader.loadClass(className);                }            }            Map<String, Class<?>> loadedClasses = myClassloader.getLoadedClasses();            XxlJobSpringExecutor xxlJobExecutor = new XxlJobSpringExecutor();            for(Map.Entry<String, Class<?>> entry : loadedClasses.entrySet()){                String className = entry.getKey();                Class<?> clazz = entry.getValue();                // 2. 将有@spring注解的类交给spring经管                // 2.1 判断是否注入spring                Boolean flag = SpringAnnotationUtils.hasSpringAnnotation(clazz);                if(flag){                    // 2.2交给spring经管                    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);                    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();                    // 此处beanName使用全旅途名是为了驻防beanName重叠                    String packageName = className.substring(0, className.lastIndexOf(".") + 1);                    String beanName = className.substring(className.lastIndexOf(".") + 1);                    beanName = packageName + beanName.substring(0, 1).toLowerCase() + beanName.substring(1);                    // 2.3注册到spring的beanFactory中                    beanFactory.registerBeanDefinition(beanName, beanDefinition);                    // 2.4允许注入和反向注入                    beanFactory.autowireBean(clazz);                    beanFactory.initializeBean(clazz, beanName);                    /*if(Arrays.stream(clazz.getInterfaces()).collect(Collectors.toSet()).contains(InitializingBean.class)){                        initBeanClass.add(clazz);                    }*/                    initBeanClass.add(clazz);                }                // 3. 带有XxlJob注解的方法注册任务                // 3.1 过滤方法                Map<Method, XxlJob> annotatedMethods = null;                try {                    annotatedMethods = MethodIntrospector.selectMethods(clazz,                            new MethodIntrospector.MetadataLookup<XxlJob>() {                                @Override                                public XxlJob inspect(Method method) {                                    return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);                                }                            });                } catch (Throwable ex) {                }                // 3.2 生成并注册方法的JobHander                for (Map.Entry<Method, XxlJob> methodXxlJobEntry : annotatedMethods.entrySet()) {                    Method executeMethod = methodXxlJobEntry.getKey();                    // 得到jobHander和Cron                    XxlJobCron xxlJobCron = executeMethod.getAnnotation(XxlJobCron.class);                    if(xxlJobCron == null){                        throw new CustomException("500", executeMethod.getName() + "(),莫得添加@XxlJobCron注解设立定时计策");                    }                    if (!CronExpression.isValidExpression(xxlJobCron.value())) {                        throw new CustomException("500", executeMethod.getName() + "(),@XxlJobCron参数内容诞妄");                    }                    XxlJob xxlJob = methodXxlJobEntry.getValue();                    jobPar.put(xxlJob.value(), xxlJobCron.value());                    if (isRegistXxlJob) {                        executeMethod.setAccessible(true);                        // regist                        Method initMethod = null;                        Method destroyMethod = null;                        xxlJobExecutor.registJobHandler(xxlJob.value(), new CustomerMethodJobHandler(clazz, executeMethod, initMethod, destroyMethod));                    }                }            }            // spring bean本色注册            initBeanClass.forEach(beanFactory::getBean);        } catch (IOException e) {            logger.error("读取{} 文献终点", fileName);            e.printStackTrace();            throw new RuntimeException("读取jar文献终点: " + fileName);        }    }}

以下是判断该类是否有spring注解的器用类广电

apublic class SpringAnnotationUtils {    private static Logger logger = LoggerFactory.getLogger(SpringAnnotationUtils.class);    /**     * 判断一个类是否有 Spring 中枢注解     *     * @param clazz 要查验的类     * @return true 若是该类上添加了相应的 Spring 注解;不然复返 false     */    public static boolean hasSpringAnnotation(Class<?> clazz) {        if (clazz == null) {            return false;        }        //是否是接口        if (clazz.isInterface()) {            return false;        }        //是否是抽象类        if (Modifier.isAbstract(clazz.getModifiers())) {            return false;        }        try {            if (clazz.getAnnotation(Component.class) != null 


Powered by 克山县名欧服务器有限公司 @2013-2022 RSS地图 HTML地图

Copyright 站群系统 © 2013-2024 SSWL 版权所有

top