下面先来说静态代理:
先来看一下UML关系图:
话不多说,直接看代码:
先看一下整体UML关系图
先来看IBuyHouse接口:
package pxx.staticproxy;
//做一个静态代理
public interface IBuyHouse {
void buyHouse();
}
再来看被代理对象,也就是目标对象ZhangSanBuyHouse
package pxx.staticproxy;
public class ZhangSanBuyHouse implements IBuyHouse{
@Override
public void buyHouse() {
System.out.println("我是张三,我要准备房子了");
}
}
然后来看代理对象BuyHouseProxy
package pxx.staticproxy;
public class BuyHouseProxy implements IBuyHouse {
//聚合一个被代理对象在里面(目标对象)
IBuyHouse buyHouse;
public BuyHouseProxy(IBuyHouse buyHouse) {
this.buyHouse = buyHouse;
}
@Override
public void buyHouse() {
System.out.println("我想要一个105平方的大房子");
buyHouse.buyHouse();
System.out.println("我付完了钱,已经买了房子了");
}
}
最后来看客户端的测试文件
package pxx.staticproxy;
public class Test {
public static void main(String[] args) {
//这里面实现两个类对象
//给代理对象传一个被代理对象进去
BuyHouseProxy buyHouseProxy = new BuyHouseProxy(new ZhangSanBuyHouse());
buyHouseProxy.buyHouse();
}
}
运行结果:
上面就把张三要代理买房子给做完了,那么假设现在李四也要来代理买房子
添加一个李四类
package pxx.staticproxy;
public class LiSiBuyHouse implements IBuyHouse {
@Override
public void buyHouse() {
System.out.println("我是李四,我也要买房子了");
}
}
然后在Test里面实现一个李四对象:
这么一看,静态代理也是可以实现多个用户进行代理啊,但是如果我不想代理买房子这个对象呢,我假如要代理 买鞋呢,那么我们又要开一个代理类,这样下去我们就会开很多代理类来做这件事儿,还有一个问题是,一旦接口增加方法,目标对象与代理对象就要维护。
下面说一下动态代理:
下面先来说JDK代理:
大致步骤:
1.目标对象实现接口,传入到代理对象里面
2.利用反射,Proxy类的newProxyInstance方法自动给我们创建一个代理对象
3.然后通过代理对象,调用目标对象的方法
先来看类图:
先来看IBuyShoes接口:
package pxx.dynamic;
public interface IBuyShoes {
public void buyShoes();
}
再来看目标对象ZhangSanBuyShoes
package pxx.dynamic;
import pxx.staticproxy.IBuyHouse;
//目标对象必须实现一个接口
public class ZhangSanBuyShoes implements IBuyShoes {
@Override
public void buyShoes() {
System.out.println("我是张三,我要准备买鞋");
}
}
在来看一个代理类ProxyFactory
package pxx.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//因为这个可以代理很多年对象
//所以直接就可以当成一个代理工厂
public class ProxyFactory {
//维护一个目标对象,这是一个Objet类型可以接收任何类型
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象动态生成一个代理对象
public Object getProxyInstance() {
//利用反射里面一个类Proxy调用newProxyInstance方法
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始");
Object res = method.invoke(target,args);
System.out.println("代理结束");
return res;
}
});
}
}
然后看一个测试类Test
package pxx.dynamic;
import pxx.staticproxy.IBuyHouse;
import pxx.staticproxy.ZhangSanBuyHouse;
public class Test {
public static void main(String[] args) {
//创建目标对象
IBuyShoes target = new ZhangSanBuyShoes();
//然后调用方法,给目标对象创建一个代理对象
//注意返回的是Object方法
IBuyShoes proxyInstance = (IBuyShoes)new ProxyFactory(target).getProxyInstance();
//然后通过代理对象调用目标对象的方法
proxyInstance.buyShoes();
}
}
运行结果
上面就解决了我们如果更改被代理对象需要创建多个代理类的问题,而且还能改变,我们如果需要在被代理类里面创建一个方法,需要在代理类里面创建多个方法 的问题。比如我们我们在添加一个代理方法
又比如在添加一个买衣服的方法
然后代理类完全不用改动直接代理就行了
上面就是JDK代理。
下面说一下Cglib代理:
前面两种代理,有一个共同点,就是要求目标对象实现一个接口,但是有时候目标对象就是一个单独对象,没有实现任何接口,这个时候我们可以使用目标对象的子类来实现代理
因为Cglib是由一系列包组成的,那么我们就要引入Cglib的jar包文件
这里再说一下两个额外注意的问题:
1.在内存中动态构建子类,不能为final,因为final类基本上来说,就是啥也干不了
2.如果目标对象方法为final/static,你不会被执行
说一下cglib大致流程:
1.实现MethodInterceptor类,利用一系列固定操作来生成一个target目标对象的子类
2. 重写intecpet方法,这个方法会当代理对象执行被代理对象方法时被触发,然后调用目标对象
话不多说,直接上代码:
先来看一下UML关系图
先来看一个被代理对象:
ZhangSanBuyShoes
package pxx.cglib;
//这个用户就不需要去实现接口
public class ZhangSanBuyShoes {
public void buyShoes() {
System.out.println("我是张三,我要买鞋");
}
}
再来看代理类ProxyFactory
package pxx.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 ProxyFactory implements MethodInterceptor {
//依旧是维护一个目标对象
private Object target;
//传入一个被代理的对象
public ProxyFactory(Object target) {
this.target = target;
}
//还要得到一个代理对象的方法
//也就是返回当前目标的代理对象
public Object getProxyInstance() {
//1.创建工具类(固定,在cglib包里面)
Enhancer enhancer = new Enhancer();
//2.设置父类(固定),传递被代理对象的class字节码文件
enhancer.setSuperclass(target.getClass());
//3.设置回掉函数(固定)
enhancer.setCallback(this);//传入的当前这个代理对象
//4.创建子类对象,即代理对象(固定)
return enhancer.create();
}
//这个方法就会帮我们去调用目标对象的方法,触发实现
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("我需要43码的鞋");
//调用目标对象的方法,传入目标对象与参数
Object res = method.invoke(target,objects);
System.out.println("我已经买好鞋了");
return res;
}
}
看Test
package pxx.cglib;
import com.sun.deploy.uitoolkit.impl.fx.AppletStageManager;
import java.util.Properties;
public class Test {
public static void main(String[] args) {
ZhangSanBuyShoes target = new ZhangSanBuyShoes();
//传递给代理对象
ZhangSanBuyShoes proxyFactory =(ZhangSanBuyShoes) new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法,触发intecept方法,然后实现目标对象调用
proxyFactory.buyShoes();
}
}
运行结果
好了,代理模式大致就说到这吧



