Skip to content

Commit

Permalink
添加extend方法
Browse files Browse the repository at this point in the history
  • Loading branch information
byx2000 committed Feb 25, 2021
1 parent 23ae05e commit def3425
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 22 deletions.
26 changes: 21 additions & 5 deletions src/main/java/byx/aop/AOP.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,35 @@ else if (target.getClass().getInterfaces().length == 0)
}

/**
* 实现接口
* @param type 接口类型
* 动态实现接口
* @param interfaceType 接口类型
* @param interceptor 方法拦截器
* @param <T> 返回类型
* @return 动态生成的接口实现类
*/
public static <T> T implement(Class<T> type, MethodInterceptor interceptor)
public static <T> T implement(Class<T> interfaceType, MethodInterceptor interceptor)
{
return type.cast(Proxy.newProxyInstance(type.getClassLoader(),
new Class<?>[]{type},
return interfaceType.cast(Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class<?>[]{interfaceType},
(proxy, method, args) -> interceptor.intercept(MethodSignature.of(method), Invokable.of(method, null), args)));
}

/**
* 动态生成子类
* @param parentType 父类
* @param interceptor 方法拦截器
* @param <T> 返回类型
* @return 动态生成的子类
*/
public static <T> T extend(Class<T> parentType, MethodInterceptor interceptor)
{
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(parentType);
enhancer.setCallback((InvocationHandler) (proxy, method, args) ->
interceptor.intercept(MethodSignature.of(method), Invokable.of(method, null), args));
return parentType.cast(enhancer.create());
}

/**
* 使用jdk动态代理
*/
Expand Down
86 changes: 69 additions & 17 deletions src/test/java/byx/aop/test/Example5.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import static byx.aop.AOP.proxy;
import static byx.aop.core.MethodMatcher.hasAnnotation;

/**
* 参数校验
*/
public class Example5
{
@Retention(RetentionPolicy.RUNTIME)
Expand All @@ -26,45 +29,94 @@ public class Example5

public interface Service
{
void login(String username, String password);
String login(String username, String password);
}

public static class ServiceImpl implements Service
{
@Validate
public void login(@NotNull String username, @NotNull String password)
public String login(@NotNull String username, @NotNull String password)
{
System.out.println("正在登录:" + username + " " + password);
return username + " " + password;
}
}

@Test
public void test()
public static class User
{
MethodInterceptor interceptor = (signature, targetMethod, params) ->
private String username;
private String password;

public String getUsername()
{
return username;
}

@Validate
public void setUsername(@NotNull String username)
{
System.out.println("username = " + username);
this.username = username;
}

public String getPassword()
{
Annotation[][] parameterAnnotations = signature.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; ++i)
return password;
}

@Validate
public void setPassword(@NotNull String password)
{
System.out.println("password = " + password);
this.password = password;
}
}

// 方法拦截器
private final MethodInterceptor interceptor = (signature, targetMethod, params) ->
{
Annotation[][] parameterAnnotations = signature.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; ++i)
{
for (Annotation annotation : parameterAnnotations[i])
{
for (Annotation annotation : parameterAnnotations[i])
if (annotation instanceof NotNull)
{
if (annotation instanceof NotNull)
{
if (params[i] == null)
throw new RuntimeException("第" + (i + 1) + "个参数为null");
}
if (params[i] == null)
throw new RuntimeException("第" + (i + 1) + "个参数为null");
}
}
return targetMethod.invoke(params);
};
}
return targetMethod.invoke(params);
};

MethodMatcher matcher = hasAnnotation(Validate.class);
// 方法匹配器
private final MethodMatcher matcher = hasAnnotation(Validate.class);

@Test
public void test1()
{
Service service = proxy(new ServiceImpl(), interceptor.when(matcher));

service.login("admin", "123456");
assertEquals("admin 123456", service.login("admin", "123456"));
assertThrows(RuntimeException.class, () -> service.login(null, "123456"));
assertThrows(RuntimeException.class, () -> service.login("admin", null));
assertThrows(RuntimeException.class, () -> service.login(null, null));
}

@Test
public void test2()
{
User user = proxy(new User(), interceptor.when(matcher));

user.setUsername("XiaoMing");
assertEquals("XiaoMing", user.getUsername());
assertThrows(RuntimeException.class, () -> user.setUsername(null));
assertEquals("XiaoMing", user.getUsername());

user.setPassword("123456");
assertEquals("123456", user.getPassword());
assertThrows(RuntimeException.class, () -> user.setPassword(null));
assertEquals("123456", user.getPassword());
}
}
71 changes: 71 additions & 0 deletions src/test/java/byx/aop/test/ExtendTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package byx.aop.test;

import byx.aop.exception.NotImplementedException;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

import static byx.aop.AOP.*;
import static byx.aop.core.MethodInterceptor.*;

public class ExtendTest
{
public static abstract class User
{
public abstract void setUsername(String username);
public abstract String getUsername();
public abstract void setPassword(String password);
public abstract String getPassword();
}

public static class Student
{
public int getId()
{
return 1001;
}

public String getName()
{
return "XiaoMing";
}
}

@Test
public void test1()
{
User user = extend(User.class, delegateTo(new Object()
{
private String username;

public void setUsername(String username)
{
this.username = username;
}

public String getUsername()
{
return username;
}
}));

user.setUsername("XiaoMing");
assertEquals("XiaoMing", user.getUsername());
assertThrows(NotImplementedException.class, () -> user.setPassword("123456"));
assertThrows(NotImplementedException.class, user::getPassword);
}

@Test
public void test2()
{
Student student = extend(Student.class, delegateTo(new Object()
{
public int getId()
{
return 2002;
}
}));

assertEquals(2002, student.getId());
assertThrows(NotImplementedException.class, student::getName);
}
}

0 comments on commit def3425

Please sign in to comment.