代理模式(Proxy pattern)
-
概念
张学友代理人!张学友只负责唱歌!面谈,签合同,安排飞机车辆,收款等其他任务全部丢给代理人
术语:通过代理,控制对对象的访问!
-
核心作用
将统一的流程控制放到代理角色中处理!可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理(即AOP的微观实现)
AOP(Aspect Oriented Propramming 面向切面编程)的核心实现机制!
-
应用场景
1:安全代理,屏蔽对真实角色的直接访问
2:远程代理,通过代理类处理远程方法调用(RMI)
3:延迟代理,先加载轻量级的代理对象,真正需要再加载真实对象
-
分类
1:静态代理(静态定义代理类)
2:动态代理(动态生成代理类)
(1)JDK自带的动态代理(常用)
(2)Javaassist字节码操作库实现
(3)CGLIB
(4)ASM,底层使用指令,可维护性较差
-
案例(明星代理)
-
静态代理
定义明星接口
public interface Star {
//面谈
public abstract void confer();
//签合同
public abstract void contract();
//订票
public abstract void book();
//唱歌
public abstract void sing();
//收钱
public abstract void collect();
}
定义真实明星类
public class RealSta implements Star{
public void confer() {
System.out.println("RealSta.confer()");
}
public void contract() {
System.out.println("RealSta.contract()");
}
public void book() {
System.out.println("RealSta.book()");
}
public void sing() {
System.out.println("张学友--饿狼传说");
}
public void collect() {
System.out.println("RealSta.collect()");
}
}
定义代理明星(除了唱歌外,其他工作都可做)
/*
* 明星代理除了不能唱歌,其他工作都可以去做
*/
public class StarProxy implements Star{
private Star star;
public StarProxy(Star star) {
super();
this.star = star;
}
public void confer() {
System.out.println("StarProxy.confer()");
}
public void contract() {
System.out.println("StarProxy.contract()");
}
public void book() {
System.out.println("StarProxy.book()");
}
//代理不会唱歌,要调用明星的sing()方法
public void sing() {
star.sing();
}
public void collect() {
System.out.println("StarProxy.collect()");
}
}
客户端测试
public class Client {
public static void main(String[] args) {
Star star = new RealStar();
StarProxy proxy = new StarProxy(star);
proxy.confer();
proxy.contract();
proxy.book();
proxy.sing();
proxy.collect();
}
}
console:
StarProxy.confer()
StarProxy.contract()
StarProxy.book()
张学友--饿狼传说
StarProxy.collect()
-
动态代理
/*
* 动态代理
*/
public class StarHandler implements InvocationHandler{
private Star star;
public StarHandler(Star star) {
super();
this.star = star;
}
//核心方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
method.invoke(star, args);
return null;
}
}
客户端测试
public class Client {
public static void main(String[] args) {
Star star = new RealStar();
StarHandler handler = new StarHandler(star);
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler);
proxy.confer();
proxy.contract();
proxy.book();
proxy.sing();
proxy.collect();
}
}
-
JDK的Proxy方式实现动态代理
-
方法
| newProxyInstance |
返回值:Object就是代理对象
参数 :loader:代表与目标对象相同的类加载器-------目标对象.getClass().getClassLoader()
interfaces:代表与目标对象实现的所有的接口字节码对象数组-----目标对象.getClass().getInterfaces()
h:具体的代理的操作,InvocationHandler接口-----new InvocationHandler(){}
注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理
-
案例
目标接口
public interface TargetInterface {
public void method1();
public String method2();
public int method3(int num);
}
目标类实现接口
public class Target implements TargetInterface{
@Override
public void method1() {
System.out.println("method1 is running!");
}
@Override
public String method2() {
System.out.println("method2 is running!");
return "mark";
}
@Override
public int method3(int num) {
System.out.println("method3 is running!");
return num;
}
}
Proxy动态代理
//动态创建代理对象
public class ProxyMark {
public static void main(String[] args) {
// 需要调用方法的目标对象
final Target target = new Target();
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target
.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InvocationHandler() {
@Override
// 被执行几次?------- 看代理对象调用方法几次
// 代理对象调用接口相应方法 都是调用invoke
/*
* proxy:是代理目标对象 method:代表的是目标方法的字节码对象 args:代表是调用目标方法时参数
*/
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 反射
Object invoke = method.invoke(target, args);// 目标对象的相应方法
// retrun返回的值给代理对象
return invoke;
}
});
proxy.method1(); // 调用invoke---Method:目标对象的method1方法 args:null 返回值null
String str = proxy.method2(); // 调用invoke---Method:目标对象的method2方法
// args:null 返回值mark
System.out.println(str);
int num = proxy.method3(10); // 调用invoke-----Method:目标对象的method3方法
// args:Object[]{100} 返回值100
System.out.println(num);
}
}
-
UML类图