java代理机制
作用:
- 对于不能或不想直接引用的对象,通过代理访问
- 通过代理去掉不能看到的内容
- 通过代理提供额外服务
Subject: 公共对外方法,表现为一个接口
RealSubject: 真正的方法实现
Proxy: 用来代理和封装RealSubject
静态代理
sqlInterface.java
1 2 3 4 5 6
| package ProxyTest;
public interface sqlInterface { public sqlInterface select(); public sqlInterface update(); }
|
sql1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package ProxyTest;
public class sql1 implements sqlInterface {
@Override public sqlInterface select() { System.out.println("selected"); return this; }
@Override public sqlInterface update() { System.out.println("updated"); return this; } }
|
sqlProxy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package ProxyTest;
import java.util.Date;
public class sqlProxy implements sqlInterface{
private sqlInterface sql = null;
public sqlProxy(sqlInterface sql) { this.sql = sql; }
@Override public sqlInterface select() { before(); sql.select(); after(); return null; }
@Override public sqlInterface update() { before(); sql.update(); after(); return null; }
private void before() { System.out.println("数据库已连接"); String start = String.format("log start time [%s] ", new Date()); System.out.println(start); }
private void after() { String end = String.format("log end time [%s] ", new Date()); System.out.println(end); System.out.println("数据库已断开"); } }
|
ProxyTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package ProxyTest;
public class ProxyTest { public static void main(String[] args) { sql1 sql = new sql1(); sqlProxy sqlProxy = new sqlProxy(sql); sqlProxy.select(); } }
|
从上的代码来看,这里使用了代理模式来实现了一个log功能。
静态代理虽然简单,但可以看到,因为接口是被限定死的,如果未来更改接口,其维护量可想而知…
动态代理
静态代理是写死的,那么动态代理顾名思义,其是动态生成的。
jdk原生动态代理
下面是上面的静态代理代码修改为动态代理后
sqlLogHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package ProxyTest;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Date;
public class sqlLogHandler implements InvocationHandler {
private sqlInterface sql = null;
public sqlLogHandler(sqlInterface sql) { this.sql = sql; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object obj = method.invoke(sql, args); after(); return obj; }
private void before() { System.out.println("数据库已连接"); String start = String.format("log start time [%s] ", new Date()); System.out.println(start); }
private void after() { String end = String.format("log end time [%s] ", new Date()); System.out.println(end); System.out.println("数据库已断开"); } }
|
sqlProxyGetter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package ProxyTest;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;
public class sqlProxyGetter {
public static sqlInterface getProxy(sqlInterface sql, InvocationHandler sqlProxy) { sqlInterface proxy = (sqlInterface) Proxy.newProxyInstance( sql.getClass().getClassLoader(), sql.getClass().getInterfaces(), sqlProxy );
return proxy; } }
|
ProxyTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package ProxyTest;
public class ProxyTest { public static void main(String[] args) { sql1 sql = new sql1(); sqlLogHandler logger = new sqlLogHandler(sql); sqlInterface proxy = sqlProxyGetter.getProxy(sql, logger); proxy.select(); } }
|
使用原生的jdk
生成代理有两个核心
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
InvocationHandler
是一个接口,包含方法invoke
,须在对应的调用处理器(这里是sqlLogHandler
)进行实现。
Proxy
是动态代理的核心类。通过静态方法newProxyInstance
来获取动态代理对象。这个方法需要三个参数,一个是接口实现类自己的类加载器,一个是其实现的所有接口,最后是一个调用处理器。
其它方法待后文更新…