Backend Development 8 min read

Hot Deployment of User‑Implemented Interfaces in Java: Annotation and Reflection Approaches

This article demonstrates how to define a simple Java interface, provide two implementation styles (Spring‑annotation and pure‑reflection), package the implementation as a JAR, and dynamically load, register, replace, or remove the implementation at runtime using URLClassLoader and Spring's bean factory.

Top Architect
Top Architect
Top Architect
Hot Deployment of User‑Implemented Interfaces in Java: Annotation and Reflection Approaches

In a recent development scenario, a system provides an interface that users can implement, package into a JAR, upload, and the system hot‑deploys and switches the implementation.

Define a simple interface

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

Simple implementation

Two implementation styles are shown: annotation‑based (managed by Spring) and reflection‑based (no Spring). The calculate method uses the annotation style, the add method uses reflection.

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

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

    // Reflection style
    @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 the JAR to a predefined directory, load it with URLClassLoader , obtain the implementation class by its fully‑qualified name, instantiate it via reflection and invoke 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 beans, scan all classes, register those annotated with @Component , @Service , or @Repository into the current Spring container.

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 or switched, the previously registered beans must be deleted from the Spring container.

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; if the JAR is not yet present, an exception is caught and the thread sleeps, allowing manual placement of the JAR.

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);
    }
}
JavareflectionSpringAnnotationHot Deploymentjar-loadingDynamic Bean Registration
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.