代理模式
代理模式和装饰器模式一样,都是在不修改原始类的情况下,增强功能。代理模式的侧重点在于扩展功能,装饰器的侧重点在于多个功能组合使用。
通过不同的代理模式,实现这样一个需求:通过代理类对 api 接口做鉴权判断,并能应用到多个接口上。
# 静态代理
public interface Controller {
void request(String param);
}
public class UserController implements Controller {
@Override
public void request(String param) {
System.out.println("request user api: " + param);
}
}
public class AuthorityControllerProxy implements Controller {
private final Controller target;
public AuthorityControllerProxy(final Controller target) {
this.target = target;
}
@Override
public void request(final String param) {
if (!"admin".equals(param)) {
System.out.println("401");
return;
}
target.request(param);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
测试类
public class WebApp {
public static void main(String[] args) {
Controller controller = new AuthorityControllerProxy(new UserController());
controller.request("user");
controller.request("admin");
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 动态代理
# JDK 实现
public interface Controller {
void request(String param);
}
public class UserController implements Controller {
@Override
public void request(String param) {
System.out.println("request user api: " + param);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
// 创建代理对象工具类
public class JdkProxyKit {
public static <T> T newProxyInstance(Object obj, InvocationHandler handler) {
final ClassLoader classLoader = obj.getClass().getClassLoader();
final Class<?>[] interfaces = obj.getClass().getInterfaces();
final Object instance = Proxy.newProxyInstance(classLoader, interfaces, handler);
return (T) instance;
}
}
// 扩展代理类功能
public class AuthorityControllerJdkProxy implements InvocationHandler {
private final Controller target;
public AuthorityControllerJdkProxy(final Controller target) {
this.target = target;
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (args == null || args.length < 1) {
System.out.println("401");
return null;
}
String param = (String) args[0];
if (!"admin".equals(param)) {
System.out.println("401");
return null;
}
return method.invoke(target, args);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
测试类
public class JdkProxyApp {
public static void main(String[] args) {
Controller controller = new UserController();
final AuthorityControllerJdkProxy handler = new AuthorityControllerJdkProxy(controller);
final Controller proxyController = JdkProxyKit.newProxyInstance(controller, handler);
System.out.println(proxyController.getClass().getName());
proxyController.request("user");
proxyController.request("admin");
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# cglib 实现
public class AdminController {
public void request(String param) {
System.out.println("request admin api: " + param);
}
}
public class AuthorityControllerCglibProxy implements MethodInterceptor {
private final Object target;
public AuthorityControllerCglibProxy(final Object target) {
this.target = target;
}
@Override
public Object intercept(final Object obj, final Method method, final Object[] args, final MethodProxy proxy) throws Throwable {
if (args == null || args.length < 1) {
System.out.println("401");
return null;
}
String param = (String) args[0];
if (!"admin".equals(param)) {
System.out.println("401");
return null;
}
return method.invoke(target, args);
}
}
public class CglibProxyKit {
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(T target, MethodInterceptor interceptor) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(interceptor);
return (T) enhancer.create();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
测试类
public class CglibProxyApp {
public static void main(String[] args) {
AdminController controller = new AdminController();
final AuthorityControllerCglibProxy proxy = new AuthorityControllerCglibProxy(controller);
final AdminController proxyController = CglibProxyKit.newProxyInstance(controller, proxy);
proxyController.request("user");
proxyController.request("admin");
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
其他 cglib 用法:https://github.com/cglib/cglib (opens new window)
# bytebuddy 实现
public class AdminController {
public void request(String param) {
System.out.println("request admin api: " + param);
}
}
public class AuthorityControllerByteBuddyProxy {
private final AdminController target;
public AuthorityControllerByteBuddyProxy(final AdminController target) {
this.target = target;
}
public void request(String param) {
if (!"admin".equals(param)) {
System.out.println("401");
return;
}
target.request(param);
}
}
public class ByteBuddyProxyKit {
@SuppressWarnings({"resource", "unchecked"})
public static <T> T newProxyInstance(Class<T> targetClass, String methodName, Object delegate)
throws InstantiationException, IllegalAccessException {
Class<?> dynamicType = new ByteBuddy()
.subclass(targetClass)
.method(ElementMatchers.named(methodName))
.intercept(MethodDelegation.to(delegate))
.make()
.load(targetClass.getClassLoader())
.getLoaded();
return (T) dynamicType.newInstance();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
测试类
public class ByteBuddyProxyApp {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
AdminController controller = new AdminController();
AuthorityControllerByteBuddyProxy proxy = new AuthorityControllerByteBuddyProxy(controller);
final AdminController proxyController = ByteBuddyProxyKit.newProxyInstance(AdminController.class, "request", proxy);
proxyController.request("user");
proxyController.request("admin");
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
其他 bytebuddy 用法:https://github.com/raphw/byte-buddy (opens new window)
Last Updated: 2024/04/23, 01:30:37