定义
- 什么是代理模式? 代理模式就是你不直接和对方打交道,而是让第三方跟他打交道,你只从第三方那里获取资源。在代码世界里,就是,我直接访问代理类Proxy ,这个类里面有你想要的资源,它负责从资源方获取资源。
分类
静态代理
没说的,先上代码…
- 资源接口:这个是目标资源
public interface Sourceable {
public void method();
}
- 这个是资源接口
public class Source implements Sourceable {
public void method() {
System.out.println("the original method!");
}
}
- 这个就是代理了
public class Proxy implements Sourceable {
private Source source;
public Proxy(){
super();
this.source = new Source();
}
public void method() {
//新增的处理,个性化处理
before();
source.method();
atfer();
}
private void atfer() {
System.out.println("after proxy!");
}
private void before() {
System.out.println("before proxy!");
}
}
- 用方法去调用
public class Test {
public static void main(String[] args) {
Sourceable source = new Proxy();
source.method();
}
}
- 输出结果:
before proxy!
the original method!
after proxy!
从上面的过程可以看出,所谓的代理就是他提前和资源方取得了联系,获取到它的资源,然后再增加了一些个性化的before atfer 方法以方便根据业务的不同来调用。这样一来就确定了他的优点: 扩展原功能,不侵入原代码。但是如果要是有10个以上的method 那么我拓展起来可就麻烦了。正是因为这个缺点才出现了第二种代理模式:动态代理。
动态代理
什么是动态代理?
- 当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
一直以为java中概念性的东西太过于术语化,本来一个简单的问题非要说的很高大上,其实我们来看下代码就知道了,千万不要对这些术语弄蒙了!
动态代理优点
- 动态代理实现了只需要将被代理对象作为参数传入代理类就可以获取代理类对象,从而实现类代理,具有较强的灵活性。
- 动态代理的服务内容不需要像静态代理一样写在每个代码块中,只需要写在invoke()方法中即可,降低了代码的冗余度。
和静态代理一样,动态代理也得先写个资源类(就这一点,还是要写接口,所以两种代理模式挺麻烦的)。
public interface Colorable {
public void value();
}
public class RedColor implements Colorable{
public void value() {
System.out.println("--------------red-------------");
}
}
这个是代理实现类
package com.heigherjavatest.designpattern.proxy.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 【Author】 技术支持史
* 【Time】2020年5月24日 下午4:17:47
* 【Function】
*/
public class ColorableAOProxy implements InvocationHandler {
private Colorable colorable;
private Colorable proxy;
public ColorableAOProxy(Colorable colorable) {
this.colorable = colorable;
this.proxy = (Colorable) Proxy.newProxyInstance(
Colorable.class.getClassLoader(),
new Class<?>[] { Colorable.class }, this);
}
public Colorable getProxy() {
return proxy;
}
/**
*proxy:代表动态代理对象
*method:代表正在执行的方法
*args:代表调用目标方法时传入的实参
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ToolUtility tool = new ToolUtility();
tool.method();
String methodName = method.getName();
System.out.println("===========starting invoke function:" + methodName
+ "==========");
Object result = method.invoke(colorable, args);
System.out.println("=========== invoke function:" + methodName
+ " success==========");
return result;
}
}
其中那个ToolUtility 是我写的另一个类:
public class ToolUtility {
public void method(){
System.out.println("运行了ToolUtility");
}
}
然后开始测试!
public class Main {
public static void main(String[] args) {
Colorable proxy = new ColorableAOProxy(new RedColor()).getProxy();
proxy.value();
}
}
输出:
所以,动态代理的好处就在于它拓展的时候是在invoke 方法里面的,因为它实现了 InvocationHandler 接口,不是实现了资源类,这样就避免了大量的代码冗余,更适合大型项目中使用。拓展方法的任务交给了invoke 不必担心Colorable 里面的抽象方法。
总结
无论是静态代理还是动态代理,写的时候读要写接口和实现接口,总体上代码量还是很多的,所以在现实案例中,我们经常在调试中看到很多代理对象,都被封装起来了。其实不止是代理模式,很多模式都做了封装,我们只需要进行调用即可,我们不用抱有太大压力去学习,只需要理解其中的原理即可。
- 欢迎大家和我一起讨论有关JAVA设计模式的问题,共同成长。