JDK代理

来源:互联网 发布:淘宝网老是要重新登录 编辑:程序博客网 时间:2024/05/21 05:06

什么是代理,什么是静态代理,什么是动态代理,什么是代理类(增强实现类),什么是委托类,为什么需要代理,代理用在什么地方等等。

刚开始接触代理时,总会有这样那样的疑问。现在我们看一下静态代理的代码,学习静态代理,更有利我们理解这些概念问题。


定义一个接口:(共同接口)

package three.day.proxy.staticproxy;

public interface ReadableInterface {
public void read();
}


定义接口实现类:(委托类,真正业务逻辑实现的地方)

接口实现类一:

package three.day.proxy.staticproxy;

public class Reader implements ReadableInterface {
@Override
public void read() {
System.out.println("reader is reading a book");
}

}

接口实现类二:

package three.day.proxy.staticproxy;

public class Student implements ReadableInterface {

@Override
public void read() {
System.out.println("student is reading a book");
}
}


说明:在平时,定义好这些实现类后,我们就可以在我们需要的地方通过new实现类,就可以调用相应的服务,如:

//临时说明加入的代码:

public static void main(String[] args){

ReadableInterface  reader = new Reader();

reader.read();

ReadableInterfacestudent = new Student();

student .read();

}

到现在,貌似我们并不需要代理的功能,就已经实现我们的需求了。

的确,你不是做框架的,使用以上代码貌似已经满足我们的需求了,顶多就把以上操作封装到一个方法中。

但是,你想想,假设你是一个开发框架的,如spring,你开发的服务中需要的参数是由外部传进来的,这样你就不能确定的说

外部传进了一个什么类型的对象,你必须考虑兼顾所有传进来的类型的可能性,所以这里就回答咯为什么需要代理,以及代理用在什么地方。

定义代理类:

package three.day.proxy.staticproxy;

public class ProxyReader implements ReadableInterface{
private ReadableInterface reader;

public ProxyReader(){}

public ProxyReader(ReadableInterface reader){
this.reader = reader;
}

@Override
public void read() {
this.reader.read();
}
}

我们看到代理类ProxyReader 与委托类(Reader Student)都实现了同样的接口ReadableInterface,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等等等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 

有以上代码:我们可以总结一下,什么是静态代理,即接口,实现类,代理类都是由我们这些程序猿写好,编译成对应的 .class 文件。

下面写代码应用上静态代理:

package three.day.proxy.staticproxy;

public class Main {

public static void main(String[] args) {
Reader reader = new Reader();
Student student = new Student();
ProxyReader proxyReader = new ProxyReader(reader);
ProxyReader proxyStudent = new ProxyReader(student);
proxyReader.read();
proxyStudent.read();
}
}


另外,这里都使用上了接口,除了具备Java中多态的特性,也是为了实现代理的功能,

在动态代理中,还要求委托类(实现类)不能是final的,这将在动态代理中继续探讨。


动态代理:

与静态代理相比,动态代理中的代理类就不是实现写好,而是通过Java的反射技术动态生成的,所以叫动态代理。

在jdk的动态代理中,主要使用到Proxy类和InvocationHandler接口动态获取一个动态代理类或者动态代理类实例对象。


下面,我将带着大家怎么使用Proxy类和InvocationHandler接口动态获取一个动态代理类或者动态代理类实例对象,这里会使用到反射技术。

定义公用接口:

package three.day.proxy.staticproxy;


public interface ReadableInterface {
public void read();
}


定义实现类:

package three.day.proxy.staticproxy;

public class Student implements ReadableInterface {
@Override
public void read() {
System.out.println("student is reading a book");
}
}


实现动态代理代码:

package three.day.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import three.day.proxy.staticproxy.ReadableInterface;
import three.day.proxy.staticproxy.Student;

public class DynamicProxyDemo01 {

public static void main(String[] args){
final Student student = new Student();//委托类对象
ClassLoader loader = student.getClass().getClassLoader();
System.out.println("ClassLoader = " + loader);
Class<?>[] interfaces = student.getClass().getInterfaces();
System.out.println(interfaces[0]);
InvocationHandler handler = new InvocationHandler() {//实现匿名代理类对象调用方法的接口,也就是说,proxy对象会调用invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("逻辑事务执行前控制代码");

//执行对象student的read方法,read方法的参数为args,retVal 是执行read方法的值,我定义的read方法没返回值,所以retVal为null
Object retVal = method.invoke(student, args);
System.out.println("逻辑事务执行后处理代码");
return retVal ;
}
};
Object proxy = Proxy.newProxyInstance(loader, interfaces, handler);
System.out.println(proxy.getClass());
ReadableInterface stu = (ReadableInterface) proxy;//之所以要使用接口,这里可以看出为什么了
stu.read();//通过代理对象调用read方法,而不是直接调用student .read(),这就是用于不用代码的区别:在invoke方法中可以做很多处理
}
}



下面再通过反射技术实现动态代理:

package three.day.proxy.dynamicproxy;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import three.day.proxy.staticproxy.ReadableInterface;
import three.day.proxy.staticproxy.Student;


public class DynamicProxyDemo02 {

public static void main(String[] args) throws SecurityException, NoSuchMethodException, 
IllegalArgumentException, InstantiationException, IllegalAccessException, 
InvocationTargetException{
final Student student = new Student();
ClassLoader loader = student.getClass().getClassLoader();
Class<?>[] interfaces = student.getClass().getInterfaces();
Class clazz = Proxy.getProxyClass(loader, interfaces);
System.out.println(clazz);
Constructor[] contructors = clazz.getConstructors();
for(Constructor c : contructors){
System.out.println(c);
}
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
ReadableInterface proxyStudent = (ReadableInterface)constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("事务执行前代码");
Object retVal = method.invoke(student, args);
System.out.println("事务执行后代码");
return retVal;
}

});
proxyStudent.read();
}
}



下面使用cglib实现动态代理:

cglib-nodep-2.1_3.jar可在spring的jar中找到。

下面看源代码:

package three.day.proxy.dynamicproxy.cglib;


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 CglibReaderProxy implements MethodInterceptor {
private Object target;

public  Object getProxy(Object target){
this.target = target;
//定义一个增强实现类对象
Enhancer enhancer = new Enhancer();
//定义该增强实现要继承的父类,所以父类不能是final的
enhancer.setSuperclass(this.target.getClass());
//设置增强实现类的回调方法
enhancer.setCallback(this);
return enhancer.create();//创建代理对象
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事务前逻辑处理");
Object retVal = proxy.invokeSuper(obj, args);
System.out.println("事务后逻辑处理");
return retVal;
}


}



package three.day.proxy.dynamicproxy.cglib;


import three.day.proxy.staticproxy.ReadableInterface;
import three.day.proxy.staticproxy.Student;


public class CglibProxyDemo01 {


public static void main(String[] args) {
CglibReaderProxy cglibReaderProxy = new CglibReaderProxy();
ReadableInterface student = new Student();
ReadableInterface proxy = (ReadableInterface)cglibReaderProxy.getProxy(student);
proxy.read();
}


}







0
0
 
 

  相关文章推荐
  •  java静态和动态代理原理
  •  java的静态与动态代理
  •  java中的静态和动态代理模式
  •  【转】Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
  •  JAVA设计模式(三)静态与动态代理模式
  •  java静态、动态代理
  •  spring技术框架基础知识二(静态)动态代理
  •  Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) (清晰,浅显)
  •  深入Java机制(一)--反射机制和动态代理机制
  •  Java动态代理
猜你在找
深度学习基础与TensorFlow实践
【在线峰会】前端开发重点难点技术剖析与创新实践
【在线峰会】一天掌握物联网全栈开发之道
【在线峰会】如何高质高效的进行Android技术开发
机器学习40天精英计划
Python数据挖掘与分析速成班
微信小程序开发实战
JFinal极速开发企业实战
备战2017软考 系统集成项目管理工程师 学习套餐
Python大型网络爬虫项目开发实战
原创粉丝点击