框架
使用代理的好处在于:当用户要求添加功能时,可以避免修改业务层代码,通过修改代理层即可实现。
静态代理
静态代理有一个缺点:代理层需要实现一遍抽象层的方法,将代码量增加一倍;
抽象层
package com.tl.demo01;
/**
* @author tl
*/
public interface Rent {
public void rent();
public void go();
public void send();
}
真实层
package com.tl.demo01;
/**
* @author tl
*/
public class Host implements Rent{
public void rent() {
System.out.println("租你3个月");
}
public void go() {
System.out.println("走吧,不租了");
}
public void send() {
System.out.println("不要钱,这房子送你了");
}
}
代理层
package com.tl.demo01;
/**
* @author tl
*/
public class Proxy implements Rent{
//组合
private Host host;
public void setHost(Host host) {
this.host = host;
}
public void rent() {
host.rent();
}
public void go() {
host.go();
add();
}
public void send() {
host.send();
delete();
}
public void add(){
System.out.println("得加钱");
}
public void delete(){
System.out.println("你说了算");
}
}
测试
import com.tl.demo01.Host;
import com.tl.demo01.Proxy;
/**
* @author tl
*/
public class Test {
@org.junit.Test
public void test1(){
Proxy proxy = new Proxy();
proxy.setHost(new Host());
proxy.rent();
proxy.go();
proxy.send();
}
}
静态代理太笨重了,需要动态代理。
动态代理
这里使用的是java jdk8中的动态代理(基于接口)
创建调用处理程序类
该类实现了InvocationHandler接口
package com.tl.demo01;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author tl
* 调用处理程序
* Invocation单词意思为召唤
* 每个代理实例都有一个关联的调用处理程序。
* 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
*/
public class ProxyInvocationHandler implements InvocationHandler {
//组合抽象层(接口)
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//获取代理实例
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
//处理代理实例上的方法调用并返回结果。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
add();
return method.invoke(rent,args);
}
public void add(){
System.out.println("得加钱");
}
public void log(String msg){
System.out.println("[Debug] 使用了一个"+msg+"方法");
}
}
抽象层(接口)
package com.tl.demo01;
/**
* @author tl
*/
public interface Rent {
public void rent();
public void go();
public void send();
}
真实层
package com.tl.demo01;
/**
* @author tl
*/
public class Host implements Rent{
public void rent() {
System.out.println("租你3个月");
}
public void go() {
System.out.println("走吧,不租了");
}
public void send() {
System.out.println("不要钱,这房子送你了");
}
}
测试
import com.tl.demo01.Host;
import com.tl.demo01.ProxyInvocationHandler;
import com.tl.demo01.Rent;
/**
* @author tl
*/
public class Test {
@org.junit.Test
public void test1(){
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//传入接口实现类
handler.setRent(new Host());
//获取相应的代理实例
Rent proxy = (Rent) handler.getProxy();
proxy.send();
proxy.go();
proxy.rent();
}
}
动态代理不需要手写代理类了,并且,在调用处理程序中添加一个方法,就可以将该方法内容添加到每一个抽象方法中