1.概述

我们在使用mybatis 的时候,我们发现实际上我们就是使用接口,没有实现类,但是spring 容器一样可以正常使用接口操作数据,这个是怎么做到的呢,实际上这里使用了代理模式和 spring的FactoryBean。
本文就用一个简单的例子来实现一个接口注入。

2.实现过程

2.1实现接口代理工厂

package com.redxun.proxydemo.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * 接口代理工厂 - 用于创建基于接口的动态代理实例
 * @param <T> 接口类型
 */
public class InterfaceProxyFactory<T> implements FactoryBean<T> {

    private final Class<T> interfaceType;

    private InvocationHandler customInvocationHandler;

    public InterfaceProxyFactory(Class<T> interfaceType) {
        if (!interfaceType.isInterface()) {
            throw new IllegalArgumentException("Class " + interfaceType.getName() + " is not an interface");
        }
        this.interfaceType = interfaceType;
    }

    /**
     * 设置自定义的调用处理器
     */
    public void setCustomInvocationHandler(InvocationHandler customInvocationHandler) {
        this.customInvocationHandler = customInvocationHandler;
    }

    @Override
    public T getObject() {
        // 使用JDK动态代理创建接口实例
        T t = (T) Proxy.newProxyInstance(
                interfaceType.getClassLoader(),
                new Class<?>[]{interfaceType},
                createInvocationHandler()
        );
        return t;
    }

    private InvocationHandler createInvocationHandler() {
        // 优先使用自定义的调用处理器
        if (customInvocationHandler != null) {
            return customInvocationHandler;
        }

        // 默认的调用处理器
        return null;
    }

    @Override
    public Class<?> getObjectType() {
        return interfaceType;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

这里最核心的代码就是 getObject 方法,这里我们使用 jdk 的代理方法,代理了接口。

2.2 实现 InvocationHandler

这个是代理类真正工作的类。

/**
 * 自定义调用处理器 - 记录方法执行时间
 */
public class TimingInvocationHandler implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = System.currentTimeMillis();

        try {
            System.out.println("【性能监控】开始执行: " + method.getName());

            // 这里可以添加真实的业务逻辑,或者返回模拟数据
            Object result = simulateBusinessLogic(method, args);

            return result;
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("【性能监控】方法 " + method.getName() + " 执行耗时: " + (endTime - startTime) + "ms");
        }
    }

    private Object simulateBusinessLogic(Method method, Object[] args) {
        // 模拟业务逻辑,返回适当的默认值
        Class<?> returnType = method.getReturnType();

        if (returnType == String.class) {
            return "模拟返回结果";
        } else if (returnType == int.class || returnType == Integer.class) {
            return 42;
        } else if (returnType == boolean.class || returnType == Boolean.class) {
            return true;
        }
        return null;
    }
}

当用户调用接口方法的时候,实际调用代理方法。

# proxy 代理服务类
# mothod调用的方法
# args 如果有参数就使用
Object invoke(Object proxy, Method method, Object[] args) 

2.3 增加一个接口

#用户实体类
public class User {
    private Long id;
    private String name;
    // getters and setters
}

# 用户接口类

public interface UserService {
    String getUserById(Long id);
    boolean saveUser(User user);
    User[] listUsers();
    void deleteUser(Long id);
}

2.4 实例化代理类并注入

@Configuration
public class ProxyConfig {

    /**
     * 注册UserService接口的代理
     */
    @Bean
    public InterfaceProxyFactory<UserService> userServiceProxy() {
        InterfaceProxyFactory<UserService> factory = new InterfaceProxyFactory<>(UserService.class);
        // 可以设置自定义的调用处理器
        factory.setCustomInvocationHandler(new TimingInvocationHandler());
        return factory;
    }


}
  • 容器中实际存储的是代理对象,而非原始的 InterfaceProxyFactory 实例
  • 任何注入 UserService 的地方都会获得这个动态生成的代理实例
  • 代理会通过 TimingInvocationHandler 来处理所有方法调用,实现额外的功能(如计时)

2.5注入接口类

@Service
public class BusinessService {

    @Autowired
    private UserService userService;


    public void executeBusinessLogic() {
        // 使用代理接口
        String user = userService.getUserById(1L);
        System.out.println("获取用户: " + user);

        boolean saved = userService.saveUser(new User());
        System.out.println("保存结果: " + saved);

    }
}

2.6 单元测试

@SpringBootTest
public class BusinessServiceTest {

    @Resource
    private BusinessService businessService;

    @Test
    public void executeBusinessLogic(){
        businessService.executeBusinessLogic();
    }

}
posted on 2025-09-14 21:42  自由港  阅读(9)  评论(0)    收藏  举报