开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情
一、代理模式
代理模式主要是使用代理对象劫持原始对象,达到对原始对象的控制
代理模式分为:
1、静态代理
2、动态代理
1.1、静态代理
//1、定义一个代理接口
public interface ITestProxy {
void test();
void login();
void register();
}
//2、实现类
public class TestProxy implements ITestProxy{
@Override
public void test(){
System.out.println("被代理对象执行了 test 方法");
}
@Override
public void login() {
System.out.println("被代理对象执行了 login 方法");
}
@Override
public void register() {
System.out.println("被代理对象执行了 register 方法");
}
}
//3、代理类
public class StaticProxy implements ITestProxy{
private final ITestProxy testProxy;
public StaticProxy(ITestProxy testProxy) {
this.testProxy = testProxy;
}
@Override
public void test(){
System.out.println("testBefore...");
testProxy.test();
System.out.println("testAfter...");
}
@Override
public void login() {
System.out.println("loginBefore...");
testProxy.login();
System.out.println("loginAfter...");
}
@Override
public void register() {
testProxy.register();
}
}
//4、测试
public class Client {
public static void main(String[] args) {
//静态代理
TestProxy testProxy = new TestProxy();
StaticProxy staticProxy = new StaticProxy(testProxy);
staticProxy.test();
staticProxy.login();
staticProxy.register();
}
}
//打印结果
testBefore...
被代理对象执行了 test 方法
testAfter...
loginBefore...
被代理对象执行了 login 方法
loginAfter...
被代理对象执行了 register 方法
可以看到,上述我们使用代理对象 StaticProxy 劫持了原始对象 TestProxy,并插入了一些 log 打印
1.2、动态代理
动态代理主要分两种:
1、JDK 动态代理
2、cglib 动态代理
1.2.1、JDK 动态代理
//1、定义一个代理接口
public interface ITestProxy {
void test();
void login();
void register();
}
//2、实现类
public class TestProxy implements ITestProxy{
@Override
public void test(){
System.out.println("被代理对象执行了 test 方法");
}
@Override
public void login() {
System.out.println("被代理对象执行了 login 方法");
}
@Override
public void register() {
System.out.println("被代理对象执行了 register 方法");
}
}
//3、定义一个动态代理 Handler
public class LogHandler implements InvocationHandler {
final Object target;
public LogHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("test".equals(method.getName())){
System.out.println("testBefore...");
Object invoke = method.invoke(target, args);
System.out.println("testAfter...");
return invoke;
}else if("login".equals(method.getName())){
System.out.println("loginBefore...");
Object invoke = method.invoke(target, args);
System.out.println("loginAfter...");
return invoke;
}
return method.invoke(target,args);
}
}
//4、测试
public class Client {
public static void main(String[] args) {
//JDK 动态代理
ClassLoader classLoader = ITestProxy.class.getClassLoader();
Class<?>[] interfaces = new Class[]{ITestProxy.class};
//动态代理对象
ITestProxy iTestProxy = (ITestProxy) Proxy.newProxyInstance(classLoader, interfaces, new LogHandler(new TestProxy()));
iTestProxy.test();
iTestProxy.login();
iTestProxy.register();
}
//打印结果
testBefore...
被代理对象执行了 test 方法
testAfter...
loginBefore...
被代理对象执行了 login 方法
loginAfter...
被代理对象执行了 register 方法
动态代理使用起来比较简单,关键方法是:java.langlreflect包下的 Proxy的newProxyInstance方法
另外需要注意:JDK 动态代理中被代理对象必须要实现一个接口。如果有一个需要被代理的对象没有实现接口,那么它就代理不了
如果我想实现被代理对象没有实现接口的这种方式要怎么办呢?
答:使用 cglib 动态代理
1.2.2、cglib 动态代理
首先我们需要进入,cglib 这个库:
implementation 'cglib:cglib:3.2.6'
接着来进行具体实现:
//1、定义一个需要被代理对象,可以看到 TestProxy 没有实现任何接口
public class TestProxy{
public void test(){
System.out.println("被代理对象执行了 test 方法");
}
public void login() {
System.out.println("被代理对象执行了 login 方法");
}
public void register() {
System.out.println("被代理对象执行了 register 方法");
}
}
//2、定义 cglib 代理类
public class CglibProxy implements MethodInterceptor {
//被代理对象
private final Object object;
public CglibProxy(Object object) {
this.object = object;
}
public Object getProxyInstance(){
//工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(object.getClass());
//设置回调函数
enhancer.setCallback(this);
//常见代理对象并返回
return enhancer.create();
}
@Override
public Object intercept(Object proxyObject, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if("test".equals(method.getName())){
System.out.println("testBefore...");
Object invoke = method.invoke(object, args);
System.out.println("testAfter...");
return invoke;
}else if("login".equals(method.getName())){
System.out.println("loginBefore...");
Object invoke = method.invoke(object, args);
System.out.println("loginAfter...");
return invoke;
}
return method.invoke(object,args);
}
}
//3、测试
public class Client {
public static void main(String[] args) {
//cglib 动态代理
TestProxy testProxy = new TestProxy();
final TestProxy cgLibTestProxy = (TestProxy) new CglibProxy(testProxy).getProxyInstance();
cgLibTestProxy.test();
cgLibTestProxy.login();
cgLibTestProxy.register();
}
}
//打印结果
testBefore...
被代理对象执行了 test 方法
testAfter...
loginBefore...
被代理对象执行了 login 方法
loginAfter...
被代理对象执行了 register 方法
可以看到 cglib 动态代理我们主要使用了 Enhancer 工具类以及实现了 MethodInterceptor 接口
Tips: 如果被代理类对象实现了接口就使用 JDK 动态代理,否则使用 cglib 动态代理
二、总结
本篇文章我们介绍了 Java 设计模式之代理模式:
1、静态代理
2、动态代理:
1、JDK 动态代理
2、cglib 动态代理
好了,本篇文章到这里就结束了,希望能给你带来帮助 🤝