前言:在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。与别的模式对比: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
JAVA语言版代理模式
一.静态代理:与动态代理比较,缺点: 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。
创建接口:
public interface Sing {
void sing();
}
创建接口实现类:
public class Singer implements Sing{
@Override
public void sing() {
System.out.println("唱歌");
}
}
创建实现类的代理类:
public class SingerProxy implements Sing {
private Sing singer;
public SingerProxy(Singer singer) {
this.singer = singer;
}
@Override
public void sing() {
System.out.println("在:" + new Date() + "时开始");
singer.sing();
System.out.println("在:" + new Date() + "时结束");
}
}
用ProxyPatternStaticsDemo类演示静态代理:
public class ProxyPatternStaticsDemo {
public static void main(String[] args) {
Sing singer =new Singer();
System.out.println(">>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<");
singer.sing();
Sing singerProxy =new SingerProxy(new Singer());
System.out.println(">>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<");
singerProxy.sing();
}
}
输出结果:
>>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<
唱歌
>>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<
在:Sun Apr 28 11:35:03 CST 2019时开始
唱歌
在:Sun Apr 28 11:35:03 CST 2019时结束
二.动态代理(JDK的API,被代理的类需要实现接口):可以解决代理类太多问题(因为代理类可以给多个类使用),注意,写动态代理一般不要用匿名类,这种用法对于动态代理没有意义。
创建接口:
public interface Sing {
void sing();
}
创建接口实现类:
public class Singer implements Sing{
@Override
public void sing() {
System.out.println("唱歌");
}
}
创建InvocationHandler接口的实现类
public class SingerInvocationHandler implements InvocationHandler {
private Object object;
public SingerInvocationHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("在:" + new Date() + "时开始");
Object invoke = method.invoke(object, args);
System.out.println("在:" + new Date() + "时结束");
return invoke;
}
}
使用ProxyPatternDynamicDemo演示动态代理:
public class ProxyPatternDynamicDemo {
public static void main(String[] args) {
Sing singer = new Singer();
System.out.println(">>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<");
singer.sing();
SingerInvocationHandler singerInvocationHandler = new SingerInvocationHandler(singer);
Sing proxy = (Sing) Proxy.newProxyInstance(singer.getClass().getClassLoader()
, singer.getClass().getInterfaces(), singerInvocationHandler);
System.out.println(">>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<");
proxy.sing();
}
}
输出结果:
>>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<
唱歌
>>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<
在:Sun Apr 28 11:39:34 CST 2019时开始
唱歌
在:Sun Apr 28 11:39:34 CST 2019时结束
三.Cglib代理(Spring的核心包):与动态代理比较:可以替代动态代理,具备动态代理所有优点,不需要实现接口,运行效率比动态代理高。
创建被代理类:
public class Singer {
public void sing() {
System.out.println("唱歌");
}
}
创建实现MethodInterceptor类的代理工厂:
public class ProxyFactory implements MethodInterceptor {
private Object object;
public ProxyFactory(Object object) {
this.object = object;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(object.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("在:" + new Date() + "时开始");
Object invoke = method.invoke(object, args);
System.out.println("在:" + new Date() + "时结束");
return invoke;
}
}
使用ProxyPatternCglibDemo演示cglib代理:
public class ProxyPatternCglibDemo {
public static void main(String[] args) {
Singer singer = new Singer();
System.out.println(">>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<");
singer.sing();
Singer proxy = (Singer) new ProxyFactory(singer).getProxyInstance();
System.out.println(">>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<");
proxy.sing();
}
}
输出结果:
>>>>>>>>>>>>不要代理类:<<<<<<<<<<<<<
唱歌
>>>>>>>>>>>>>使用代理类之后:<<<<<<<<<<<<
在:Sun Apr 28 14:44:04 CST 2019时开始
唱歌
在:Sun Apr 28 14:44:04 CST 2019时结束