java动态代理常用于做权限控制,细粒度权限如对方法的操作是否有权限,如果在每个方法前都判断一下用户是否有权限是非常麻烦的,因此用代理实现给每个方法前自动加上判断的功能。使用jdk的proxy类来实现代理。
一、静态代理:
/**
* 这是真是对象要继承的抽象类
* @author 罗辉
* @time 2013-4-15下午10:21:55
*/
public abstract class subject {
public abstract void rentHouse();
}
/**
* 真实对象继承抽象类,有一个方法
* @author 罗辉
* @time 2013-4-15下午10:26:12
*/
public class RealSubject extends subject {
@Override
public void rentHouse() {
System.out.println("租房子");
}
}
/**
* 代理类也有一个相同的方法,但是他实际上确是通过真实类realsubject类来实现的
* 并可以在方法前后做一些自己的操作
* @author 罗辉
* @time 2013-4-15下午10:24:25
*/
public class ProxySubject {
public void rentHouse() {
premethod();
RealSubject realSubject=new RealSubject();
realSubject.rentHouse();
postmethod();
}
private void premethod(){
System.out.println("房子租出去之前要做的事");
}
private void postmethod(){
System.out.println("房子租出去之后要做的事");
}
}
/**
* 静态代理
* 通过代理类来操作真实类
* 但是每个真实类要对应一个代理类,导致类数量的膨胀
* @author 罗辉
* @time 2013-4-15下午10:43:56
*/
public class Client {
public static void main(String[] args) {
ProxySubject proxySubject = new ProxySubject();
proxySubject.rentHouse();
}
}
二、动态代理:
总结使用动态代理的步骤:
1、创建一个要被代理的真实类,以及该类所实现的接口
2、创建一个实现了InvocationHandler接口的代理类,它必须实现invoke方法
3、通过Proxy的静态方法newInstance(ClassLoader c,Class[] interfaces,InvocationHandler h)来创建一个代理
4、通过代理来调用方法
/**
* 真实类要实现的接口
* @author 罗辉
* @time 2013-4-15下午10:52:03
*/
public interface Subject {
public void rentHouse();
}
/**
* 真实类
* @author 罗辉
* @time 2013-4-15下午10:52:32
*/
public class RealSubject implements Subject {
public void rentHouse() {
System.out.println("租房子");
}
}
/**
* 代理类,需要传入一个真实对象,实现了InvocationHandler的接口
* 代理类肯定是要通过真实对象来处理方法的
* @author 罗辉
* @time 2013-4-15下午10:35:55
*/
public class ProxySubject implements InvocationHandler{
private Object realObject;
public ProxySubject(Object realObject) {
this.realObject=realObject;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(realObject, args);
}
}
/**
* 动态代理,这是springAop的一种实现方法,另外一种使用第三方的cglib
* 通过代理类来获取一个InvocationHandler
* 如何获得代理类?使用Proxy的newProxyInstance动态创建一个代理类(一个代理Proxy可以为多个真实类服务),然后由代理类执行方法
* 第二个参数是要实现哪些接口,可以实现多个
* @author 罗辉
* @time 2013-4-15下午10:39:29
*/
public class Client {
public static void main(String[] args) {
//在实际情况下,我们是通过spring的配置文件来获取realsubject的定义的,在此假设new一个出来
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new ProxySubject(realSubject);
Class<?> clazz = realSubject.getClass();
Subject subject = (Subject) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), handler);
subject.rentHouse();
}
}