#1. 代理模式
代理模式是 JAVA 的一种设计模式,形成条件如下:a. 客户端不能直接调用目标类的时候,让客户端调用目标类的代理类b.代理类和目标类实现相同的接口
c. 代理类将所有的方法调用分派到目标对象上,且可添加前置通知(校验等)和后置处理(打印日志等)代理可分为静态代理和动态代理
#2. 静态代理
由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
a. 接口声明及实现b. 创建代理类并实现接口public interface Account { public String queryAccount(); } public class AccountImpl implements Account{ @Override public String queryAccount() { System.out.println("查询成功"); return null; } }
c. 调用public class AccountProxy implements Account{ private AccountImpl accountImpl; public AccountProxy(AccountImpl accountImpl) { super(); this.accountImpl = accountImpl; } @Override public String queryAccount() { System.out.println("...前置通知..."); accountImpl.queryAccount(); System.out.println("...后置处理..."); return null; } }
public class TestProxy { public static void main(String[] args) { AccountProxy ap = new AccountProxy(new AccountImpl()); ap.queryAccount(); } }
由于只能一个代理对应一个接口,易产生多个代理类,固换下方动态代理
#3. 动态代理
##1. JDK 动态代理(使用InvocationHandler接口和Proxy类)
在程序运行时,运用反射机制动态创建
a. 接口声明及实现public interface Account { public String queryAccount(); } public class AccountImpl implements Account{ @Override public String queryAccount() { System.out.println("查询成功"); return null; } }
b. 创建代理类并实现接口
c. 调用public class AccountProxy implements InvocationHandler{ private Object target; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("...代理start..."); result = method.invoke(target, args); System.out.println("...代理end..."); return result; } public Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }
public class TestProxy { public static void main(String[] args) { AccountProxy ap = new AccountProxy(); Account account = (Account)ap.bind(new AccountImpl()); account.queryAccount(); } }
JDK 动态代理依靠接口实现,如果有些类并没有实现接口,就要使用 CGLIB 动态代理
##2. CGLIB 动态代理(使用MethodInterceptor接口和Enhancer类)
CGLIB 的底层采用ASM字节码生成,比 JDK 代理效率高
a. 创建类public class Account { public String queryAccount(); }
b. 创建代理类并实现接口public class AccountProxy implements MethodInterceptor{ private Object target; @Override public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable { Object result = null; System.out.println("...代理start..."); result = proxy.invokeSuper(obj, arg); System.out.println("...代理end..."); return result; } public Object bind(Object target){ this.target = target; Enhancer eh = new Enhancer(); eh.setSuperclass(this.target.getClass()); eh.setCallback(this); return eh.create(); } }
c. 调用
public class TestProxy { public static void main(String[] args) { AccountProxy ap = new AccountProxy(); Account account = (Account)ap.bind(new Account()); account.queryAccount(); } }
因为采用的是继承,所以CGLIB不能代理final类