Backend Development 8 min read

Hot Deployment of Custom Interface Implementations in Java Using Reflection and Spring

This article demonstrates how to define a simple Calculator interface, provide both annotation‑based and reflection‑based implementations, and dynamically hot‑deploy user‑supplied JAR files by loading them with URLClassLoader, registering Spring beans, and handling bean removal on JAR deletion.

Architecture Digest
Architecture Digest
Architecture Digest
Hot Deployment of Custom Interface Implementations in Java Using Reflection and Spring

Define Simple Interface

First, a Calculator interface with calculate and add methods is defined.

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

Implementation Class

The implementation provides two ways: annotation‑based ( calculate ) and reflection‑based ( add ). It injects CalculatorCore to demonstrate bean dependency construction.

@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

Simple component providing the add operation.

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

Reflection‑Based Hot Deployment

Upload a JAR to a predefined directory, load it with URLClassLoader , obtain the implementation class by 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);
}

Spring‑Based Hot Deployment

If the uploaded JAR contains Spring components, scan all classes, register beans whose classes carry @Component , @Service , or @Repository annotations 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());
        }
    }
}

Utility Methods

DeployUtils provides methods to read all class entries from a JAR, determine whether a class is a Spring bean, and transform class names to bean IDs.

public static Set
readJarFile(String jarAddress) throws IOException { /* ... */ }
public static boolean isSpringBeanClass(Class
cla) { /* ... */ }
public static String transformName(String className) { /* ... */ }

Bean Removal on JAR Deletion

When a JAR is removed, the previously registered beans are also deregistered 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 Harness

A simple 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);
    }
}
JavaBackend DevelopmentreflectionSpringHot Deploymentjar-loading
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

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.