代理,是一种设计模式,主要作用是为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
主要分为两大代理:静态代理、动态代理(JDK动态代理、CGLIB动态代理)
以下面的例子为例,卖房人、代理方、买房人,买卖人双方不需要打交道,通过和代理方打交道,卖房人提供房子给代理方,不需要自己去找买方,代理方有一堆卖房信息,买方直接找代理方即可
接口
public interface IHome {void say();
}
被代理类
public class ForlanHome implements IHome{@Overridepublic void say() {System.out.println("卖程序员Forlan房子啦!!!");}
}
public class HomeProxy implements IHome {IHome home;public HomeProxy(IHome home) {this.home = home;}@Overridepublic void say() {System.out.println("This is HomeProxy");home.say();}
}
public static void main(String[] args) {ForlanHome forlanHome = new ForlanHome();HomeProxy homeProxy = new HomeProxy(forlanHome);homeProxy.say();}
实现InvocationHandler接口重写invoke方法
public class HomeInvocationHandler implements InvocationHandler {IHome home;public HomeInvocationHandler(IHome home) {this.home = home;}/*** 重写invoke方法** @param proxy 生成的代理对象* @param method 调用的方法* @param args 方法入参* @return*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method " + method.getName() + " start!");Object o = method.invoke(home, args);System.out.println("method " + method.getName() + " end!");return o;}
}
测试方法
public static void main(String[] args) {IHome forlanHome = new ForlanHome();IHome home = (IHome) Proxy.newProxyInstance(IHome.class.getClassLoader(),new Class[]{IHome.class},new HomeInvocationHandler(forlanHome));home.say();
}
引入反射封装,方便调用
public class CommonInvocationHandler implements InvocationHandler {T obj;public T getProxyObj(T t) {obj = t;T proxyInstance = (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);return proxyInstance;}/*** 重写invoke方法** @param proxy 生成的代理对象* @param method 调用的方法* @param args 方法入参* @return*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method " + method.getName() + " start..");Object o = method.invoke(obj, args);System.out.println("method " + method.getName() + " end!");return o;}
}
测试方法
public static void main(String[] args) {IHome forlanHome = new ForlanHome();CommonInvocationHandler commonInvocationHandler = new CommonInvocationHandler<>();IHome proxyObj = commonInvocationHandler.getProxyObj(forlanHome);proxyObj.say();
}
第三方,需要导入jar包
cglib cglib 2.2.2
实现MethodInterceptor,重写intercept方法
public class HomeMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("method " + method.getName() + " start!");Object result = null;result = methodProxy.invokeSuper(o, objects);System.out.println("method " + method.getName() + " end!");return result;}
}
测试方法
public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ForlanHome.class); // 被代理对象的classenhancer.setCallback(new HomeMethodInterceptor()); // 设置回调,方法拦截器ForlanHome forlanHome = (ForlanHome)enhancer.create(); // 生成动态代理类forlanHome.say();
}
使用泛型,封装Enhancer代码,方便调用
public class CommonMethodInterceptor implements MethodInterceptor {public T getProxyObj(Class tClass) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(tClass); // 被代理对象的classenhancer.setCallback(this); // 设置回调,方法拦截器return (T) enhancer.create(); // 生成动态代理类}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("method " + method.getName() + " start!");Object result = null;result = methodProxy.invokeSuper(o, objects);System.out.println("method " + method.getName() + " end!");return result;}
}
测试方法
public static void main(String[] args) {CommonMethodInterceptor commonMethodInterceptor = new CommonMethodInterceptor<>();ForlanHome proxyObj = commonMethodInterceptor.getProxyObj(ForlanHome.class);proxyObj.say();
}
代理对象实现被代理对象的接口,通过调用代理接口的接口,实现代理功能
分离代理行为和被代理对象,替被代理对象干某件事
JDK动态代理
面向接口的动态代理,代理一个对象去增强面向某个接口中定义的方法
缺点:被代理对象必须实现接口
CGLIB动态代理
面向类的动态代理,重写父类方法,增强使用
缺点: final类不能被代理
上一篇:STM32F103定时计算方法
下一篇:深入了解Java中的SQL注入