Spring中基于条件创建带双实现的自定义注解接口动态代理咨询
解决方案
1. 基础定义:自定义注解与目标类
先明确自定义注解标注接口、实现类实现该接口的结构:
// 自定义注解,标注需要代理的接口 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ProxyTargetInterface { } // 被注解标注的业务接口 @ProxyTargetInterface public interface UserService { void doBusiness(); } // 接口的业务实现类 @Service public class UserServiceImpl implements UserService { @Override public void doBusiness() { System.out.println("执行原业务逻辑"); } }
2. 两种代理逻辑实现
(1)保留原逻辑的代理(支持增强)
基于JDK动态代理实现,可在原逻辑前后添加增强操作:
public class RetainLogicHandler implements InvocationHandler { private final Object targetBean; public RetainLogicHandler(Object targetBean) { this.targetBean = targetBean; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 可选:添加前置增强(如日志、权限校验) System.out.println("代理前置增强"); // 执行原业务逻辑 Object result = method.invoke(targetBean, args); // 可选:添加后置增强 System.out.println("代理后置增强"); return result; } }
(2)无业务逻辑的占位代理
直接返回默认值,不触发原业务逻辑:
public class PlaceholderLogicHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 根据返回值类型返回默认值 Class<?> returnType = method.getReturnType(); if (returnType.isPrimitive()) { if (returnType == boolean.class) return false; if (returnType == int.class) return 0; // 其他基本类型可按需补充 } return null; } }
3. 条件控制代理并纳入Spring上下文
核心是通过BeanPostProcessor替换Spring容器中的原Bean为代理对象,确保代理被Spring管理:
@Component public class ProxySwitchProcessor implements BeanPostProcessor { // 可从配置文件读取,比如@Value("${proxy.mode:retain}") private final String proxyMode = "retain"; // 可选值:retain / placeholder @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // 检查当前Bean是否实现了被@ProxyTargetInterface标注的接口 Class<?>[] interfaces = bean.getClass().getInterfaces(); for (Class<?> iface : interfaces) { if (iface.isAnnotationPresent(ProxyTargetInterface.class)) { // 根据模式创建对应代理 if ("retain".equals(proxyMode)) { return Proxy.newProxyInstance( bean.getClass().getClassLoader(), interfaces, new RetainLogicHandler(bean) ); } else if ("placeholder".equals(proxyMode)) { return Proxy.newProxyInstance( bean.getClass().getClassLoader(), interfaces, new PlaceholderLogicHandler() ); } } } return bean; } }
4. 验证代理生效
通过Spring注入代理对象测试效果:
@SpringBootTest public class ProxyTest { @Autowired private UserService userService; @Test public void testProxyBehavior() { userService.doBusiness(); // retain模式:输出代理增强日志 + 原业务逻辑 // placeholder模式:无业务逻辑输出,仅返回默认值 } }
注意事项
- 若目标类无接口,可替换为CGLIB代理(用
Enhancer创建类代理)。 - 代理模式可通过配置中心或环境变量动态控制,无需硬编码。
- 之前手动创建代理未纳入Spring上下文,是因为未替换容器中原Bean实例,此方案通过
BeanPostProcessor完成替换,确保代理对象被Spring管理。
内容的提问来源于stack exchange,提问作者Kaspersky
相关产品推荐
相关产品推荐

