代理的作用:为了安全,远程调用,屏蔽客户端直接访问真实对象等,如:dubbo中的远程调用就使用 了代理。
以下为具体实现:
1.接口:
package proxy;
import java.util.List;
public interface Query {
List<String> queryList();
String getName();
}
2.实现类:
package proxy;
import java.util.List;
public class QueryImpl implements Query{
@Override
public List<String> queryList() {
return null;
}
/**
* @Title: getName
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @return 参数
* @author shidebin
* @date 2018年10月9日
* @throws
*/
@Override
public String getName() {
return "ss";
}
}
2.静态代理:
package proxy;
import java.util.List;
public class StaticProxy implements Query{
private QueryImpl query= null;
@Override
public List<String> queryList() {
if(query == null) {
query = new QueryImpl();
}
return query.queryList();
}
/**
* @Title: getName
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @return 参数
* @author shidebin
* @date 2018年10月9日
* @throws
*/
@Override
public String getName() {
if(query == null) {
query = new QueryImpl();
}
return query.getName();
}
}
缺点:有几个方法要写几个实现,比较麻烦。
3.用java JDK API实现动态代理:
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler{
private QueryImpl query;
public JDKProxy(QueryImpl query) {
this.query = query;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(query, args);
}
public static Query createQueryProxy() {
return (Query)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader()
, new Class[] {Query.class}, new JDKProxy(new QueryImpl()));
}
}
4.用cglib实现动态代理:
package proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private QueryImpl query = null;
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
if(query == null) {
query = new QueryImpl();
}
return arg1.invoke(query, arg2);
}
public static Query createQuery() {
Enhancer hancer= new Enhancer();
hancer.setCallback(new CglibProxy());
hancer.setInterfaces(new Class[] {Query.class});
return (Query)hancer.create();
}
}
5.俩种动态代理的性能比较:
package proxy;
public class ProxyTest {
public static void main(String[] args) {
int circle = 30000000;
long begin = System.currentTimeMillis();
Query jdk = JDKProxy.createQueryProxy();
System.out.println("jdk create:"+(System.currentTimeMillis() - begin));
begin = System.currentTimeMillis();
for(int i = 0;i<circle;i++) {
jdk.queryList();
}
System.out.println("jdk query:"+(System.currentTimeMillis() - begin));
begin = System.currentTimeMillis();
for(int i = 0;i<circle;i++) {
jdk.getName();
}
System.out.println("jdk getName:"+(System.currentTimeMillis() - begin));
Query lib = CglibProxy.createQuery();
System.out.println("lib create:"+(System.currentTimeMillis() - begin));
begin = System.currentTimeMillis();
for(int i = 0;i<circle;i++) {
lib.queryList();
}
System.out.println("lib query:"+(System.currentTimeMillis() - begin));
begin = System.currentTimeMillis();
for(int i = 0;i<circle;i++) {
lib.getName();
}
System.out.println("lib getName:"+(System.currentTimeMillis() - begin));
}
}
输出:
jdk create:4
jdk query:63
jdk getName:130
lib create:228
lib query:137
lib getName:144
运行环境是jdk1.8,可以看出jdk自带的动态代理效率要高