您的位置:首页 > 编程语言 > Java开发

JAVA笔记——代理模式

2016-04-01 15:18 501 查看
什么是代理

静态代理

JDK实现动态代理

cglib动态代理

什么是代理

举个生活中的例子:有时候我们想要买火车票,但是火车站太远,那么我们可以去附近的火车票代售点进行购买。此时,代售点就是代理,它拥有被代理对象的部分功能——售票功能。

而在编程中,代理类同样拥有被代理类部分功能,但是不仅如此,代理类可以在此基础之上附加一些自己的功能

代理类最常见的用法就是日志功能:在被代理类执行方法之前,写下日志。

静态代理

需求:

现有一只鸟,它有一个fly方法,我们想在它fly的时候,写下日志

先写一个flyable接口:

public interface Flyable {

void fly();
}


写一个bird,实现接口

public class Bird implements Flyable {

@Override
public void fly() {
System.out.println("bird is flying....");
}

}


写一个日志代理类,注意,代理类也要实现同样的接口

public class LogProxy implements Flyable {

private Flyable f;

public LogProxy(Flyable f){
this.f = f;
}

@Override
public void fly() {
System.out.println("log is writing...");

f.fly();

System.out.println("over...");
}

}


测试:

public static void main(String[] args) {

Bird bird = new Bird();

Flyable f = new LogProxy(bird);

f.fly();

}


结果:



静态代理的缺陷也很明显,它只能代理实现了相同接口的类。随着系统业务的增长,需要代理的类可能非常多,那我们也要写非常多的代理类

因此,我们需要动态代理

JDK实现动态代理

JDK为我们提供了动态代理的能力。动态代理的优势在于,它不依赖于任何接口或类

我们先写好一个flyable和bird

public interface Flyable {

void fly();
}


public class Bird implements Flyable {

@Override
public void fly() {
System.out.println("bird is flying....");
}

}


JDK的动态代理,我们需要实现接口InvocationHandler,例如我们写一个日志的动态代理

public class LogHandler implements InvocationHandler {

private Object target;

public LogHandler(Object target) {
super();
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("log is writing...");

method.invoke(target, null);

System.out.println("over...");

return null;
}

}


从上面代理类也可以看出,它不依赖于任何的类和接口

测试:

public class Test {

public static void main(String[] args) {

Bird bird = new Bird();

InvocationHandler h = new LogHandler(bird);

Class<?> cls = bird.getClass();

ClassLoader loader = cls.getClassLoader();

Flyable f = (Flyable) Proxy.newProxyInstance(loader, cls.getInterfaces(), h);

f.fly();

}

}


结果:



JDK的动态代理也有一定的缺陷,它要求被代理的类必须实现某个接口,也就是说,JDK的动态代理是根据接口来实现的

cglib动态代理

除了JDK动态代理,我们也可以使用cglib来实现,二者的却别在于:cglib的动态代理是根据类来实现的,JDK的是根据接口来实现的

写一个bird类,有fly方法

public class Bird {

public void fly(){
System.out.println("bird is flying...");
}
}


代理类:实现MethodInterceptor接口。cglib创建的代理类事实上是被代理类的子类,使用Enhancer来创建

public class LogProxy implements MethodInterceptor {

private Enhancer enhancer = new Enhancer();

/**
* 创建代理类
* @param cls
* @return
*/
public Object getProxy(Class cls){
//设置父类
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
//创建子类
return enhancer.create();
}

/**
* 拦截目标类的方法
* 参数:
* obj 被代理的对象
* m 被代理的对象的方法
* args 方法的参数
* proxy 代理类实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args,
MethodProxy proxy) throws Throwable {

//此处我们可以做日志等操作
System.out.println("log .......");

//cglib创建的代理类其实是被代理类的子类,此处执行父类的方法,即执行被代理类真正要执行的方法
proxy.invokeSuper(obj, args);

return null;
}

}


测试:

public class Test {

public static void main(String[] args) {

LogProxy proxy = new LogProxy();
Bird bird = (Bird) proxy.getProxy(Bird.class);
bird.fly();

}

}


结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java jdk