代理模式,即ProxyPattern,java常用设计模式之一,动态代理实现了著名的AOP思想。代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。
通俗的讲,可以拿到现实中来举例,可能说的并不准确,比如,苹果出了一款iphone手机,拿到中国交给代理商来卖,如联通、电信,就是所谓的定制机,联通电信又给iphone手机植入了一些软件,再卖给使用者。我们最后买到的手机就是代理商处理过的。
静态代理很好理解,代码类似如下:
原类:
package staticProxy;public class Object { public void service() { // do something }} |
---|
代理类:
package staticProxy;public class ProxyObject { private staticProxy.Object obj; public ProxyObject(staticProxy.Object obj) { this.obj = obj; } public void service() { // do something this.obj.service(); }} |
---|
静态代理需要对每个原类创建一个代理类,这样做需要代理的情况少的话还可以接受,如果多的话,就无法接受了,所以我们需要一种动态创建代理类的方式。
Java支持动态代理,可以在运行期根据原对象来动态创建代理对象。有两种方式可以实现动态代理,一种是通过JDK Proxy,另一种是第三方类库CGLIB,前者得到的代理对象是实现和原类相同的接口,后者得到的是继承自原类。下面主要介绍的是JDK Proxy。
Proxy类中有个newProxyInstance方法,可以通过该方法得到代理对象,该方法有三个参数:
ClassLoader loader:原类的类加载器;
Class[] interfaces:原类实现的接口列表;
InvocationHandler handler:指派方法调用的调用处理程序。
调用该方法创建代理对象时,会把InvocationHandler传入$Proxy内,并根据相应接口生成方法,每个方法内都调用InvocationHandler中的invoke方法,在invoke方法中执行相应方法。
Advice.java,增强类,用于创建代理对象时增强功能。
public class Advice { /** 前置增强 */ public void beforeMethod() { System.out.println("前置增强"); } /** 后置增强 */ public void afterMethod() { System.out.println("后置增强"); } /** 异常增强 */ public void catchMethod() { System.out.println("异常增强"); } /** 最后执行增强 */ public void finallyMethod() { System.out.println("最后增强"); }} |
---|
ProxyFactory.java,代理类工厂,用于产生代理对象。
public class ProxyFactory { /** 代理类的增强对象 */ private Advice advice; /** 代理的目标对象 */ private Object target; public ProxyFactory() {} public ProxyFactory(Advice advice, Object target) { this.advice = advice; this.target = target; } /** * 得到代理对象 * @return */ public Object getProxy() { Object proxy = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() { /** * 代理对象需要执行的方法 */ public Object invoke(Object proxy, Method method, Object[] args) { Object result = null; advice.beforeMethod(); try { result = method.invoke(target, args); advice.afterMethod(); } catch (Exception e) { advice.catchMethod(); } finally { advice.finallyMethod(); } return result; } }); return proxy; } public void setAdvice(Advice advice) { this.advice = advice; } public void setTarget(Object target) { this.target = target; }} |
---|
ITest.java,目标对象接口。
public interface ITest { void test();} |
---|
Test.java,目标对象类。
public class Test implements ITest { public void test() { System.out.println("目标对象"); } public static void main(String[] args) { ProxyFactory pf = new ProxyFactory(new Advice(), new Test()); ITest test = (ITest) pf.getProxy(); test.test(); }} |
---|
输出结果:
前置增强目标对象后置增强最后增强 |
---|
动态代理实现了AOP思想,AOP弥补了OOP的不足。本篇主要介绍的是jdk proxy动态代理的使用方式,对AOP没有特意说明。