ソースを参照

add Spring cglib support

Looly 6 年 前
コミット
94c824e03d

+ 2 - 0
CHANGELOG.md

@@ -11,6 +11,8 @@
 * 【core   】     修改StrUtil.equals逻辑,改为contentEquals
 * 【core   】     增加URLUtil.UrlDecoder
 * 【core   】     增加XmlUtil.setNamespaceAware,getByPath支持UniversalNamespaceCache
+* 【core   】     增加XmlUtil.setNamespaceAware,getByPath支持UniversalNamespaceCache
+* 【aop    】     增加Spring-cglib支持,改为SPI实现
 
 ### Bug修复
 * 【json   】     修复解析JSON字符串时配置无法传递问题

+ 8 - 0
hutool-aop/pom.xml

@@ -19,6 +19,7 @@
 	<properties>
 		<!-- versions -->
 		<cglib.version>3.3.0</cglib.version>
+		<spring.version>5.2.5.RELEASE</spring.version>
 	</properties>
 
 	<dependencies>
@@ -34,5 +35,12 @@
 			<scope>compile</scope>
 			<optional>true</optional>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-core</artifactId>
+			<version>${spring.version}</version>
+			<scope>compile</scope>
+			<optional>true</optional>
+		</dependency>
 	</dependencies>
 </project>

+ 2 - 0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/CglibInterceptor.java

@@ -1,6 +1,7 @@
 package cn.hutool.aop.interceptor;
 
 import cn.hutool.aop.aspects.Aspect;
+import cn.hutool.core.lang.Console;
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
 
@@ -42,6 +43,7 @@ public class CglibInterceptor implements MethodInterceptor, Serializable {
 		if (aspect.before(target, method, args)) {
 			try {
 //				result = proxy.invokeSuper(obj, args);
+				Console.log(target);
 				result = proxy.invoke(target, args);
 			} catch (InvocationTargetException e) {
 				// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)

+ 65 - 0
hutool-aop/src/main/java/cn/hutool/aop/interceptor/SpringCglibInterceptor.java

@@ -0,0 +1,65 @@
+package cn.hutool.aop.interceptor;
+
+import cn.hutool.aop.aspects.Aspect;
+import org.springframework.cglib.proxy.MethodInterceptor;
+import org.springframework.cglib.proxy.MethodProxy;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Spring-cglib实现的动态代理切面
+ *
+ * @author looly
+ */
+public class SpringCglibInterceptor implements MethodInterceptor, Serializable {
+	private static final long serialVersionUID = 1L;
+
+	private final Object target;
+	private final Aspect aspect;
+
+	/**
+	 * 构造
+	 *
+	 * @param target 被代理对象
+	 * @param aspect 切面实现
+	 */
+	public SpringCglibInterceptor(Object target, Aspect aspect) {
+		this.target = target;
+		this.aspect = aspect;
+	}
+
+	/**
+	 * 获得目标对象
+	 *
+	 * @return 目标对象
+	 */
+	public Object getTarget() {
+		return this.target;
+	}
+
+	@Override
+	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
+		final Object target = this.target;
+		Object result = null;
+		// 开始前回调
+		if (aspect.before(target, method, args)) {
+			try {
+//				result = proxy.invokeSuper(obj, args);
+				result = proxy.invoke(target, args);
+			} catch (InvocationTargetException e) {
+				// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)
+				if (aspect.afterException(target, method, args, e.getTargetException())) {
+					throw e;
+				}
+			}
+		}
+
+		// 结束执行回调
+		if (aspect.after(target, method, args, result)) {
+			return result;
+		}
+		return null;
+	}
+}

+ 28 - 20
hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java

@@ -1,46 +1,59 @@
 package cn.hutool.aop.proxy;
 
-import java.io.Serializable;
-
 import cn.hutool.aop.aspects.Aspect;
 import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.ServiceLoaderUtil;
+
+import java.io.Serializable;
 
 /**
  * 代理工厂<br>
  * 根据用户引入代理库的不同,产生不同的代理对象
- * 
- * @author looly
  *
+ * @author looly
  */
-public abstract class ProxyFactory implements Serializable{
+public abstract class ProxyFactory implements Serializable {
 	private static final long serialVersionUID = 1L;
 
 	/**
 	 * 创建代理
 	 *
-	 * @param <T> 代理对象类型
+	 * @param <T>         代理对象类型
+	 * @param target      被代理对象
+	 * @param aspectClass 切面实现类,自动实例化
+	 * @return 代理对象
+	 * @since 5.3.1
+	 */
+	public <T> T proxy(T target, Class<? extends Aspect> aspectClass) {
+		return proxy(target, ReflectUtil.newInstanceIfPossible(aspectClass));
+	}
+
+	/**
+	 * 创建代理
+	 *
+	 * @param <T>    代理对象类型
 	 * @param target 被代理对象
 	 * @param aspect 切面实现
 	 * @return 代理对象
 	 */
 	public abstract <T> T proxy(T target, Aspect aspect);
-	
+
 	/**
 	 * 根据用户引入Cglib与否自动创建代理对象
-	 * 
-	 * @param <T> 切面对象类型
-	 * @param target 目标对象
+	 *
+	 * @param <T>         切面对象类型
+	 * @param target      目标对象
 	 * @param aspectClass 切面对象类
 	 * @return 代理对象
 	 */
-	public static <T> T createProxy(T target, Class<? extends Aspect> aspectClass){
+	public static <T> T createProxy(T target, Class<? extends Aspect> aspectClass) {
 		return createProxy(target, ReflectUtil.newInstance(aspectClass));
 	}
 
 	/**
 	 * 根据用户引入Cglib与否自动创建代理对象
-	 * 
-	 * @param <T> 切面对象类型
+	 *
+	 * @param <T>    切面对象类型
 	 * @param target 被代理对象
 	 * @param aspect 切面实现
 	 * @return 代理对象
@@ -51,15 +64,10 @@ public abstract class ProxyFactory implements Serializable{
 
 	/**
 	 * 根据用户引入Cglib与否创建代理工厂
-	 * 
+	 *
 	 * @return 代理工厂
 	 */
 	public static ProxyFactory create() {
-		try {
-			return new CglibProxyFactory();
-		} catch (NoClassDefFoundError e) {
-			// ignore
-		}
-		return new JdkProxyFactory();
+		return ServiceLoaderUtil.loadFirstAvailable(ProxyFactory.class);
 	}
 }

+ 25 - 0
hutool-aop/src/main/java/cn/hutool/aop/proxy/SpringCglibProxyFactory.java

@@ -0,0 +1,25 @@
+package cn.hutool.aop.proxy;
+
+import cn.hutool.aop.aspects.Aspect;
+import cn.hutool.aop.interceptor.SpringCglibInterceptor;
+import org.springframework.cglib.proxy.Enhancer;
+
+/**
+ * 基于Spring-cglib的切面代理工厂
+ * 
+ * @author looly
+ *
+ */
+public class SpringCglibProxyFactory extends ProxyFactory{
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public <T> T proxy(T target, Aspect aspect) {
+		final Enhancer enhancer = new Enhancer();
+		enhancer.setSuperclass(target.getClass());
+		enhancer.setCallback(new SpringCglibInterceptor(target, aspect));
+		return (T) enhancer.create();
+	}
+
+}

+ 3 - 0
hutool-aop/src/main/resources/META-INF/services/cn.hutool.aop.proxy.ProxyFactory

@@ -0,0 +1,3 @@
+cn.hutool.aop.proxy.CglibProxyFactory
+cn.hutool.aop.proxy.SpringCglibProxyFactory
+cn.hutool.aop.proxy.JdkProxyFactory

+ 1 - 1
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java

@@ -23,7 +23,7 @@ public class AopTest {
 	}
 
 	@Test
-	public void aopByCglibTest() {
+	public void aopByAutoCglibTest() {
 		Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class);
 		String result = dog.eat();
 		Assert.assertEquals("狗吃肉", result);