Backend Development 11 min read

Hot Deployment of User-Implemented Java Interfaces Using Reflection and Spring

This article explains how to let users upload a JAR that implements a given Java interface, then hot‑deploy the new implementation either via reflection or Spring annotation, covering interface definition, code examples, bean registration, removal, and testing.

Top Architect
Top Architect
Top Architect
Hot Deployment of User-Implemented Java Interfaces Using Reflection and Spring

In a recent development scenario, a system requires users to upload a JAR implementing a given interface, and the system must hot‑deploy and switch to the new implementation.

Define a simple interface

Using a calculator example, the interface is defined as:

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

Simple implementation

The implementation can be managed by Spring (annotation mode) or without Spring (reflection mode). The code is:

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

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

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

The supporting core class:

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

Reflection‑based hot deployment

Users upload the JAR to a predefined directory (jarAddress, jarPath). The system loads the JAR with a URLClassLoader, obtains the implementation class by its full name, creates an instance via reflection, and invokes the method.

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

If the uploaded JAR contains Spring components, the system scans all classes, registers beans that have Spring annotations into the current Spring container, achieving dynamic bean registration.

public static void hotDeployWithSpring() throws Exception {
    Set
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());
        }
    }
}

Delete JAR and remove beans

When a JAR is removed, the corresponding Spring beans must also be deregistered using the same bean name transformation.

public static void delete() throws Exception {
    Set
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));
        }
    }
}

Test

A test loop repeatedly attempts hot deployment, sleeping when the JAR is not yet present.

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);
    }
}
BackendJavareflectionSpringdependency injectionHot Deploymentjar-loading
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.