解析动态代理

静态代理:每个代理类和被代理类实现同一个接口,代理类通过构造方法中的参数实现二者之间的绑定,缺点每个接口及其实现都需要一个代理类。
动态代理:java.lang.reflect.InvocationHandler 接口 Proxy类
先说明一下反射
使用Java反射API的时候可以绕过Java默认的访问控制检查,比如可以直接获取到对象的私有域的值或是调用私有方法。只需要在获取到Constructor、Field和Method类的对象之后,调用setAccessible方法并设为true即可。有了这种机制,就可以很方便的在运行时刻获取到程序的内部状态。

我们在使用动态代理中最重要的一个类是Proxy,一个接口是InvocationHandler.
Proxy 提供用于动态创建代理类和实例的方法,它还是有这些方法创建的所有动态代理类的超类。
创建某一接口foo的代理:
InvocationHandler handler = new MyInvocationHandler(…);
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader,new Class[] {foo.class});
Foof=(Foo)proxyClass.getConstructor(newClass[] {InvacationHandler.class}).newInstance(new Object[] {hnadler});

该类的字段InvacationHandler h;//此代理实例的 调用处理程序
方法:

    Class <?> getProxyClass(ClassLoader loader,Class<?>… interfaces)

返回代理类的java.lang.Class并需要向其提供类加载器和接口数组 该代理类由指定类加载器定义,并将实现提供的所有的接口。如果该类加载器已经定义了具有相同接口的代理类,那么现有的代理类将会被返回。否则类加载器动态生成具有这些接口的代理类。
传递给getProxyClass()的参数是有限制的:
1、 interfaces必须是接口的自描述类 而不能是类的自描述类。
2、 interfaces数组中的自描述类不能描述同一个接口。
3、 所有接口类型的名称通过特定的类加载器必须可见。

Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

返回一个带有代理类指定调用处理程序的代理实例。
getProxyClass 返回的是代理类 newProxyInstance返回的是代理类实现对象。

isProxyClass(Class<?>)判断一个自描述类是否是由getProxyClass() 或者newProxyInstance()生成的代理类的自描述类。
InvocationHandler getInvocationHandler(Object proxy);返回指定代理实例的调用处理程序
总结:通过一个代理接口的代理实例上的方法调用将会被指派到实例的调用处理程序的Invoke方法,并传递代理实例,识别调用方法的java.lang.reflect.Mathod 对象,以及包含参数的Object数组

使用Java 动态代理的两个重要步骤
  1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
  2. 通过为Proxy类的newProxyInstance方法指定代理类的ClassLoader 对象和代理要实现的interface以及调用处理器InvocationHandler对象 来创建动态代理类的对象;
    代码如下
private Object delegate;
    public Object bind(Object obj) {

        this.delegate = obj;
        return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(), this.delegate.getClass().getInterfaces(), this);
    }
    Logger logger = Logger.getLogger(this.getClass().getName());

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        logger.log(Level.INFO, "更新前");
        Object obj = method.invoke(delegate, args);
        logger.log(Level.INFO, "更新后----");

        return obj;
    }
动态代理类优缺点

优点
1.动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。
2.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
缺点
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
开发自己的拦截器
实现包com.opensymphony.xwork2.interceptor.Interceptor接口该接口类定义代码如下

Public interface Interceptor extends serializable{
Void destroy();
Void init();
String intercept (ActionInvocation invocation) throws Exception}

//该方法是用户需要实现的拦截动作,就像Action的execute的方法一样,intercept方法返回一个字符串作为逻辑视图。如果该方法直接返回一个字符串,系统将会跳转到该逻辑视图对应的实际试图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的action 的引用,可以通过该参数的invoke 方法,将控制权传给下个拦截器,或者传给Action的execute方法。

自己拦截器的配置
<interceptors>
    <interceptor name=”” class=””>
        <param name=””>value</param>
    </interceptor>
</interceptors>
<action name=”” class=””>
    <interceptor-ref name=””>
        <param name =””>覆盖参数<param>
    </interceptor-ref>
</action>

简单的拦截器将在execute方法前面执行之前 执行之后的动作都定义在拦截器的intercetpt()方法中为了精确的定义在execute()方法执行结束之后,在处理物理资源转向之前的动作,struts2提供了用于拦截结果的监听器。这个监听器是手动注册在拦截器内部的。想如下代码:
invocation.addPreResultListener(new MyPreResultListener());
在拦截器的intercept方法内通过ActionInvocation参数可以获得ActionContext。便可以做权限控制。获取session 从而判断是否 某个用户登录,或者登陆的用户是否具有某些性质从而判断是否转向实际的物理资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值