一、代理模式的简介
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问;
- 归类:创建型模式
- 目的:拿到目标类的引用,能够调用业务类的方法;
二、代理模式的必须具备的条件
- 必须要两个角色:执行者、被代理人;
- 被代理人必须有一件要做的事情但是没有时间做亦或者不想做;
- 对于代理人来说,必须要获取被代理人的个人信息。
三、静态代理和动态代理的区别
- 静态代理类返回值必须是具体的类(在代理之前,所有的东西都是已知的)–不方便扩展
- 动态代理类返回值可以不是具体的类(在代理之前,所有的东西都是未知的)–方便扩展
四、静态代理的实现
- 定义要做的事情接口:Person.java
package com.demo.proxy.statics;
/**
* 用户找房子
*/
public interface Person {
public void findHome();
}
- 被代理类:XiaoFeiYang.java
package com.demo.proxy.statics;
/**
* 被代理人:小肥羊
* 要做的事情:找房子
* 要求:找一个3室一厅、坐北朝南、带阳台的房子
*/
public class XiaoFeiYang implements Person {
@Override
public void findHome() {
//工作太多了,产品突然加了10价格需求,没有时间找房子
System.out.println("找一个3室一厅、坐北朝南、带阳台的房子");
}
}
- 代理类:Intermediary.java
package com.demo.proxy.statics;
/**
* 代理人:中介
*/
public class Intermediary {
private Person person;
public Intermediary(Person person){
this.person = person;
}
//目标对象的引用给拿到
public void findHome(){
System.out.println("根据你的要求找房中..........");
this.person.findHome();
System.out.println("找到了:这个房子刚好满足你的条件");
}
}
- 测试:StaticProxyTest.java
package com.demo.proxy.statics;
public class StaticProxyTest {
public static void main(String[] args) {
//中介帮小肥羊找房
Intermediary intermediary = new Intermediary(new XiaoFeiYang());
intermediary.findHome();
//实现出来了,但是发现木有,代理类(Intermediary)真心不能扩展了哦
}
}
- 测试结果:
根据你的要求找房中..........
找一个3室一厅、坐北朝南、带阳台的房子
找到了:这个房子刚好满足你的条件
五、jdk动态代理的实现
- 接口:Person2.java
package com.demo.proxy.jdk;
public interface Person2 {
public void findHome();
public void findGirlFriend();
}
- 被代理对象:XiaoFeiYang2.java
package com.demo.proxy.jdk;
/**
* 被代理人:小肥羊
*/
public class XiaoFeiYang2 implements Person2{
@Override
public void findHome() {
System.out.println("找一个3室一厅、坐北朝南、带阳台的房子");
}
@Override
public void findGirlFriend() {
System.out.println("找女朋友,身材S型,皮肤白里透红,身高170CM,出的厅堂下得厨房,晚上还能暖床,善解人意,有自己的性格和想法");
}
}
- 代理:Intermediary2.java
package com.demo.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理人:三方代理
*/
public class Intermediary2 implements InvocationHandler {
//持有被代理人的引用
private Person2 person2;
public Object getInstance(Person2 person2) throws Exception{
this.person2=person2;
Class<?> clazz=person2.getClass();
//生成一个新的对象(实际就是字节码重组)
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是三方代理:我要给你找对象,现在已经拿到你的需求");
System.out.println("寻找中..........");
method.invoke(this.person2,args);
System.out.println("如果合适的话,就准备办喜事吧,emmmmmmmm");
return null;
}
}
- 测试类:JDKProxyTest.java
package com.demo.proxy.jdk;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
/**
* Created by Tom on 2018/3/10.
*/
public class JDKProxyTest {
public static void main(String[] args) {
try {
Person2 obj = (Person2)new Intermediary2().getInstance(new XiaoFeiYang2());
System.out.println(obj.getClass());
obj.findGirlFriend();
//在这里,我们可以看到 输出里面有个 class com.sun.proxy.$Proxy0,来我们反编译下,看看是什么东西
byte[] bytes=ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{Person2.class});
//输出文件到E盘
FileOutputStream os = new FileOutputStream("F://$Proxy0.class");
os.write(bytes);
os.close();
//通过反编译文件
} catch (Exception e) {
e.printStackTrace();
}
}
}
六、cglib动态代理的实现
被代理类
package com.demo.proxy.cglib;
/**
* 被代理人:小肥羊
* 要做的事情:找房子
* 要求:找一个3室一厅、坐北朝南、带阳台的房子
*/
public class XiaoFeiYang2 {
public void findHome() {
//工作太多了,产品突然加了10价格需求,没有时间找房子
System.out.println("找一个3室一厅、坐北朝南、带阳台的房子");
}
}
代理类:
package com.demo.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理人:中介
*/
public class Intermediary2 implements MethodInterceptor {
public Object getInstance(Class<?> clazz){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//这里我是不是可以给任何人代理做事情?
//比如我给人当媒婆,给人代驾等等。。。
System.out.println("我是中介哦:我要给你找房子");
System.out.println("现在已经拿到你的需求");
methodProxy.invokeSuper(o,objects);
System.out.println("开始找...........");
System.out.println("找到合适的,准备付钱吧");
return null;
}
}
测试类:
package com.demo.proxy.cglib;
public class Test {
public static void main(String[] args) {
XiaoFeiYang2 obj = (XiaoFeiYang2)new Intermediary2().getInstance(XiaoFeiYang2.class);
obj.findHome();
}
}
网友评论