代理
前言
代理是java中很有用的知识点,通过代理,我们可以在不删除原有代码的基础上,增加一些新的功能,换句话说就是增强了代码的活度。
一、最简单的代理
原理解析:
- 按照常理讲,一般我们实现一个功能,常用的方法是是先编写接口,然后实现该接口的所有功能。
- 代理与该方法的唯一区别是这个功能不用你亲自实现了,我来帮你实现。
- 最简单的步骤是,这里有一个接口,里面有若干个功能,写一个代理类,该代理拥有功能接口类的一个属性,并且有该属性的有参构造方法
- 让代理实现功能接口,并且重写该方法,同时增加一些新的功能
代码示例:
写在前面,此小节以下内容为超简单代理示例,并且所有的类放在同一包即可。
- BuyCar.java(接口)
首先写一个超简单接口
public interface BuyCar {
void buy();
}
- BuyCarImpl.java
写一个类实现该接口
public class BuyCarImpl implements BuyCar{
@Override
public void buy() {
System.out.println("成功购买一辆兰博基尼!");
}
}
- BuyCarProxy.java
编写代理类
public class Proxy implements BuyCar {
private BuyCar buyCar;
public Proxy(BuyCar buyCar) {
this.buyCar = buyCar;
}
@Override
public void buy() {
System.out.println("===========购买前==============");
buyCar.buy();
System.out.println("===========购买后==============");
}
}
- 测试类
public static void main(String[] args) {
BuyCarImpl buyCar = new BuyCarImpl();
Proxy proxy = new Proxy(buyCar);
proxy.buy();
}
二、更进一步:动态代理
原理解析:
- 实现动态代理的关键是是利用java自己提供的代理类
InvocationHandler
来实现。 - 该代理类是一个接口,需要我们实现,并且重写invoke()方法。
- invoke()方法需要传入三个参数,类加载器,接口类,代理实现类。
代码示例:
- BuyCar.java
- BuyCarImpl.java
- DynamicProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class newProxy implements InvocationHandler {
private BuyCar buyCar;
public newProxy(BuyCar buyCar) {
this.buyCar = buyCar;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("===========购买前==============");
buyCar.buy();
System.out.println("===========购买后==============");
return null;
}
}
4.测试类
public static void main(String[] args) {
BuyCar buyCar = (BuyCar) Proxy.newProxyInstance(BossTest.class.getClassLoader(), new Class[]{BuyCar.class}, new newProxy(new BuyCarImpl()));
buyCar.buy();
}
三、接口代理(重要!!!)
前面的铺垫都是为了接口代理而实现的。从这里的内容往下都很重要。
原理解析:
- 接口代理才是代理的精髓,在第一和第二小节中,我们本质上都离不开接口实现类来实现方法。
- 接口代理是相当于省略了接口实现类。
- 直接看如何实现
代码实现:
- DailyAction.java
public interface DailyAction {
void eat();
void sleep();
void play();
}
- ApiProxy.java
mport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ApiProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
switch (name){
case "eat":
System.out.println("我在吃饭!");
break;
case "sleep":
System.out.println("我在睡觉!");
break;
case "play":
System.out.println("我在玩游戏!");
break;
default:
}
return null;
}
}
3.Test.java(测试类)
public static <T> T getApi(Class<T> apiClass){
ApiProxy apiProxy = new ApiProxy();
return (T)Proxy.newProxyInstance(apiClass.getClassLoader(),new Class[]{apiClass},apiProxy);
}
@org.junit.Test
public void test(){
DailyAction api = getApi(DailyAction.class);
System.out.println(api);
}