与上篇动态代理文章对比,写出如下静态代理代码:
//接口1
package com.jingProxy;
public interface Person {
public void sing(String name);
}
//要被代理类(委托类)
package com.jingProxy;
public class ZhangLu implements Person {
@Override
public void sing(String name) {
System.out.println("唱"+name);
}
}
//代理类
package com.jingProxy;
public class JingProxy implements Person {
private Person person;
public JingProxy(Person person) {
super();
this.person = person;
}
@Override
public void sing(String name) {
System.out.println("before");
person.sing(name);
System.out.println("after");
}
}
//应用测试类
package com.jingProxy;
public class JingTest {
public static void main(String[] args) {
Person p = new ZhangLu();
JingProxy jingProxy = new JingProxy(p);
jingProxy.sing("er地方");
}
}
与动态代理相比,接口和被代理类没变化,代理类不同
静态代理 | 动态代理 |
代理类实现的是被代理类的抽象接口 | 实现InvocationHandler接口 |
事先知道要代理什么 | 直到运行时才知道自己要代理什么 |
程序员代码实现,再进行编辑 | 运行时通过反射机制实现 |
下面对静态代理进行详细介绍
1、什么是代理
我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品。关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者”对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就相当于为厂家做了一次对客户群体的“过滤”。我们把微商代理和厂家进一步抽象,前者可抽象为代理类,后者可抽象为委托类(被代理类)。通过使用代理,通常有两个优点,并且能够分别与我们提到的微商代理的两个特点对应起来:
优点一:可以隐藏委托类的实现;
优点二:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。
2. 静态代理
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。 下面我们用Vendor类代表生产厂家,BusinessAgent类代表微商代理,来介绍下静态代理的简单实现,委托类和代理类都实现了Sell接口,Sell接口的定义如下:
- public interface Sell { void sell(); void ad();
- }
Vendor类的定义如下:
- public class Vendor implements Sell { public void sell() {
- System.out.println("In sell method");
- } public void ad() {
- System,out.println("ad method")
- }
- }
代理类BusinessAgent的定义如下:
- public class Vendor implements Sell { public void sell() {
- System.out.println("In sell method");
- } public void ad() {
- System,out.println("ad method")
- }
- }
从BusinessAgent类的定义我们可以了解到,静态代理可以通过聚合来实现,让代理类持有一个委托类的引用即可。
下面我们考虑一下这个需求:给Vendor类增加一个过滤功能,只卖货给大学生。通过静态代理,我们无需修改Vendor类的代码就可以实现,只需在BusinessAgent类中的sell方法中添加一个判断即可如下所示:
- public class BusinessAgent implements Sell {
- ...
- public void sell() {
- if (isCollegeStudent()) {
- vendor.sell();
- }
- }
- ...
- }
这对应着我们上面提到的使用代理的第二个优点:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。静态代理的局限在于运行前必须编写好代理类,下面我们重点来介绍下运行时生成代理类的动态代理方式。
动态代理可参看我博客另一篇文章