Why Manual JAR Deployment Is Outdated and How Dynamic Hot‑Deploy Makes It Easy

This article walks through defining a simple Calculator interface, provides two implementation styles, and demonstrates both reflection‑based and annotation‑based hot‑deployment of uploaded JARs in a Spring application, including bean registration, removal, and a test loop.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Why Manual JAR Deployment Is Outdated and How Dynamic Hot‑Deploy Makes It Easy

Define a Simple Interface

Example of a Calculator interface with calculate and add methods.

public interface Calculator {
    int calculate(int a, int b);
    int add(int a, int b);
}

Simple Implementation

Two implementations: annotation‑based (managed by Spring) and reflection‑based.

@Service
public class CalculatorImpl implements Calculator {
    @Autowired
    CalculatorCore calculatorCore;

    // annotation way
    @Override
    public int calculate(int a, int b) {
        int c = calculatorCore.add(a, b);
        return c;
    }

    // reflection way
    @Override
    public int add(int a, int b) {
        return new CalculatorCore().add(a, b);
    }
}

CalculatorCore

@Service
public class CalculatorCore {
    public int add(int a, int b) {
        return a + b;
    }
}

Reflection‑Based Hot Deployment

Upload JAR path, load with URLClassLoader, instantiate class, invoke add.

private static String jarAddress = "E:/zzq/IDEA_WS/CalculatorTest/lib/Calculator.jar";
private static String jarPath = "file:/" + jarAddress;

public static void hotDeployWithReflect() throws Exception {
    URLClassLoader urlClassLoader = new URLClassLoader(
        new URL[]{ new URL(jarPath) }, Thread.currentThread().getContextClassLoader());
    Class clazz = urlClassLoader.loadClass("com.nci.cetc15.calculator.impl.CalculatorImpl");
    Calculator calculator = (Calculator) clazz.newInstance();
    int result = calculator.add(1, 2);
    System.out.println(result);
}

Annotation‑Based Hot Deployment

Load JAR, scan classes, register beans whose classes carry Spring stereotypes.

public static void hotDeployWithSpring() throws Exception {
    Set<String> classNameSet = DeployUtils.readJarFile(jarAddress);
    URLClassLoader urlClassLoader = new URLClassLoader(
        new URL[]{ new URL(jarPath) }, Thread.currentThread().getContextClassLoader());
    for (String className : classNameSet) {
        Class clazz = urlClassLoader.loadClass(className);
        if (DeployUtils.isSpringBeanClass(clazz)) {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            defaultListableBeanFactory.registerBeanDefinition(
                DeployUtils.transformName(className), beanDefinitionBuilder.getBeanDefinition());
        }
    }
}

Removing Beans When JAR Is Deleted

Iterate classes, if Spring bean, remove its definition from the same BeanFactory.

public static void delete() throws Exception {
    Set<String> classNameSet = DeployUtils.readJarFile(jarAddress);
    URLClassLoader urlClassLoader = new URLClassLoader(
        new URL[]{ new URL(jarPath) }, Thread.currentThread().getContextClassLoader());
    for (String className : classNameSet) {
        Class clazz = urlClassLoader.loadClass(className);
        if (DeployUtils.isSpringBeanClass(clazz)) {
            defaultListableBeanFactory.removeBeanDefinition(DeployUtils.transformName(className));
        }
    }
}

DeployUtils Helper Methods

Methods to read all class names from a JAR, check for Spring annotations, and convert class names to bean IDs.

public static Set<String> readJarFile(String jarAddress) throws IOException {
    Set<String> classNameSet = new HashSet<>();
    JarFile jarFile = new JarFile(jarAddress);
    Enumeration<JarEntry> entries = jarFile.entries();
    while (entries.hasMoreElements()) {
        JarEntry jarEntry = entries.nextElement();
        String name = jarEntry.getName();
        if (name.endsWith(".class")) {
            String className = name.replace(".class", "").replaceAll("/", ".");
            classNameSet.add(className);
        }
    }
    return classNameSet;
}

public static boolean isSpringBeanClass(Class<?> cla) {
    if (cla == null || cla.isInterface() || Modifier.isAbstract(cla.getModifiers())) {
        return false;
    }
    return cla.getAnnotation(Component.class) != null ||
           cla.getAnnotation(Repository.class) != null ||
           cla.getAnnotation(Service.class) != null;
}

public static String transformName(String className) {
    String tmpstr = className.substring(className.lastIndexOf(".") + 1);
    return tmpstr.substring(0, 1).toLowerCase() + tmpstr.substring(1);
}

Test Loop

Continuously attempts hot deployment; if the JAR is not found, catches the exception, waits ten seconds, then retries.

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
while (true) {
    try {
        hotDeployWithReflect();
        // hotDeployWithSpring();
        // delete();
    } catch (Exception e) {
        e.printStackTrace();
        Thread.sleep(1000 * 10);
    }
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaReflectionSpringHot DeploymentJAR LoadingDynamic Bean Registration
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.