Skip to content

Commit

Permalink
切面代理工具中的cglib支持多参数构造生成
Browse files Browse the repository at this point in the history
  • Loading branch information
looly committed May 24, 2023
1 parent 99c5e13 commit 2e88e74
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 6 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# 🚀Changelog

-------------------------------------------------------------------------------------------------------------
# 5.8.19.M1 (2023-05-23)
# 5.8.19.M1 (2023-05-25)

### 🐣新特性
* 【db 】 优化HttpRequest.toString()内容打印(issue#3072@Github)
Expand All @@ -16,6 +16,7 @@
* 【core 】 增加CsvWriteConfig.setEndingLineBreak配置项(issue#I75K5G@Gitee)
* 【core 】 增加Tailer追踪文件时文件被删除的处理情况(pr#3115@Github)
* 【core 】 DelegatedExecutorService构造方法设置成public(issue#I77LUE@Gitee)
* 【core 】 切面代理工具中的cglib支持多参数构造生成(issue#I74EX7@Gitee)

### 🐞Bug修复
* 【core 】 修复URLUtil.decode无法解码UTF-16问题(issue#3063@Github)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import cn.hutool.aop.aspects.Aspect;
import cn.hutool.aop.interceptor.CglibInterceptor;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Constructor;

/**
* 基于Cglib的切面代理工厂
*
Expand All @@ -14,12 +18,46 @@ public class CglibProxyFactory extends ProxyFactory{
private static final long serialVersionUID = 1L;

@Override
@SuppressWarnings("unchecked")
public <T> T proxy(T target, Aspect aspect) {
final Class<?> targetClass = target.getClass();

final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibInterceptor(target, aspect));
return (T) enhancer.create();
return create(enhancer, targetClass);
}

/**
* 创建代理对象<br>
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
* 某些对象存在非空参数构造,则需遍历查找需要的构造完成代理对象构建。
*
* @param <T> 代理对象类型
* @param enhancer {@link org.springframework.cglib.proxy.Enhancer}
* @param targetClass 目标类型
* @return 代理对象
*/
@SuppressWarnings("unchecked")
private static <T> T create(final Enhancer enhancer, final Class<?> targetClass) {
final Constructor<?>[] constructors = ReflectUtil.getConstructors(targetClass);
Class<?>[] parameterTypes;
Object[] values;
IllegalArgumentException finalException = null;
for (final Constructor<?> constructor : constructors) {
parameterTypes = constructor.getParameterTypes();
values = ClassUtil.getDefaultValues(parameterTypes);

try {
return (T) enhancer.create(parameterTypes, values);
} catch (final IllegalArgumentException e) {
//ignore
finalException = e;
}
}
if (null != finalException) {
throw finalException;
}

throw new IllegalArgumentException("No constructor provided");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import cn.hutool.aop.aspects.Aspect;
import cn.hutool.aop.interceptor.SpringCglibInterceptor;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import org.springframework.cglib.proxy.Enhancer;

import java.lang.reflect.Constructor;

/**
* 基于Spring-cglib的切面代理工厂
*
Expand All @@ -14,12 +18,46 @@ public class SpringCglibProxyFactory extends ProxyFactory{
private static final long serialVersionUID = 1L;

@Override
@SuppressWarnings("unchecked")
public <T> T proxy(T target, Aspect aspect) {
final Class<?> targetClass = target.getClass();

final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new SpringCglibInterceptor(target, aspect));
return (T) enhancer.create();
return create(enhancer, targetClass);
}

/**
* 创建代理对象<br>
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
* 某些对象存在非空参数构造,则需遍历查找需要的构造完成代理对象构建。
*
* @param <T> 代理对象类型
* @param enhancer {@link Enhancer}
* @param targetClass 目标类型
* @return 代理对象
*/
@SuppressWarnings("unchecked")
private static <T> T create(final Enhancer enhancer, final Class<?> targetClass) {
final Constructor<?>[] constructors = ReflectUtil.getConstructors(targetClass);
Class<?>[] parameterTypes;
Object[] values;
IllegalArgumentException finalException = null;
for (final Constructor<?> constructor : constructors) {
parameterTypes = constructor.getParameterTypes();
values = ClassUtil.getDefaultValues(parameterTypes);

try {
return (T) enhancer.create(parameterTypes, values);
} catch (final IllegalArgumentException e) {
//ignore
finalException = e;
}
}
if (null != finalException) {
throw finalException;
}

throw new IllegalArgumentException("No constructor provided");
}
}
91 changes: 91 additions & 0 deletions hutool-aop/src/test/java/cn/hutool/aop/test/IssueI74EX7Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

package cn.hutool.aop.test;

import cn.hutool.aop.aspects.SimpleAspect;
import cn.hutool.aop.proxy.CglibProxyFactory;
import cn.hutool.aop.proxy.JdkProxyFactory;
import cn.hutool.aop.proxy.ProxyFactory;
import cn.hutool.aop.proxy.SpringCglibProxyFactory;
import cn.hutool.core.lang.Console;
import lombok.Setter;
import org.junit.Test;

public class IssueI74EX7Test {
@Test
public void proxyTest() {
final SmsBlend smsBlend = new SmsBlendImpl(1);
final ProxyFactory engine = new JdkProxyFactory();
engine.proxy(smsBlend, new SimpleAspect());
}

/**
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
* Enhancer.create()默认调用无参构造,有参构造或者多个构造没有很好的兼容。
*
*/
@Test
public void cglibProxyTest() {
final SmsBlend smsBlend = new SmsBlendImpl(1);
final ProxyFactory engine = new CglibProxyFactory();
engine.proxy(smsBlend, new SimpleAspect());
}

/**
* https://gitee.com/dromara/hutool/issues/I74EX7<br>
* Enhancer.create()默认调用无参构造,有参构造或者多个构造没有很好的兼容。
*
*/
@Test
public void springCglibProxyTest() {
final SmsBlend smsBlend = new SmsBlendImpl(1);
final ProxyFactory engine = new SpringCglibProxyFactory();
engine.proxy(smsBlend, new SimpleAspect());
}

@Test
public void springCglibProxyWithoutConstructorTest() {
final SmsBlend smsBlend = new SmsBlendImplWithoutConstructor();
final ProxyFactory engine = new SpringCglibProxyFactory();
engine.proxy(smsBlend, new SimpleAspect());
}

public interface SmsBlend{
void send();
}

public static class SmsBlendImpl implements SmsBlend{

private final int status;

public SmsBlendImpl(final int status) {
this.status = status;
}

@Override
public void send() {
Console.log("sms send." + status);
}
}

@Setter
public static class SmsBlendImplWithoutConstructor implements SmsBlend{

private int status;

@Override
public void send() {
Console.log("sms send." + status);
}
}
}

0 comments on commit 2e88e74

Please sign in to comment.