Spring AOP 原理分析 2 动态代理

动态代理:

这是一个常用设计模式。为什么需要代理,在现实生活中需要代理的情况很多,比如类似的助理职务等。在软件中,也有很多,比如代理服务器,在办公室上网一般都要经过代理服务器去访问外网,代理服务器中公司会做一些限制,比如一些购物网站不可以访问、流量限制等等。这就是代理的作用。在编程中,我们需要代理方法,这个方法可以帮我们做一些额外的工作比如日志、权限等。不同方法需要不同的代理方法,这就是动态代理。
有一个目标对象 RealObject,在代理模式中,我们再设计一个,接口和目标对象一致的代理对象Proxy,凡是需要调用目标对象的地方,都可以有代理对象来完成。

Spring AOP的核心就是动态代理,动态代理也是jdk的一个特性。通过JDK的动态代理特性,可以为任意的Java对象创建代理对象。

我们来看下在Java中是如何创建代理对象的。此对象要有一个接口。
在Java中提供了一个类Proxy,有一个生成代理对象的方法:

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

调用这个方法,就可以生成一个代理对象,这个对象如何与目标对象的方法进行关联呢,是通过这个最后一个参数InvocationHandler h,如果
这个参数为空,会抛出异常。这个InvocationHander 是一个接口,有个invoke方法,使用时,我们需要创建一个他的实现类,比如RealHandler,然后将这个实现类传入到上述方法中。这个RealHandler中自然就需要实现这个invoke方法:

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { doBefore(); method.invoke(target, args); doAfter() ; return null; } 

就是在这个invoke方法中,加入代理所需要做的方法,然后通过method.invoke的回调调用原来的方法,method.invoke有两个参数,第一个是目标对象的实例,第二个是目标对象所调用方法的参数。这个method是所调用的那个方法。 Method和args都可以从InvocationHandler的invoke中取得,还需要一个目标对象的设置,这个需要我们手动设置:

private Object target;

     public RealHandler(Object target){
         super();
         this.target = target;
     }

下面将全部的代码贴出来:

package com.csair.aop;

public class RealObjectI implements RealObject{

    @Override
    public String realMethod(String s) {
        System.out.println("target 打印S:"+s);
        return null;
    }
}
package com.csair.aop;

public interface RealObject {

    public String  realMethod(String s);
    //如何在此方法 执行之前 做些操作,如果在方法返回之后做一些操作
    }
package com.csair.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class RealHandler implements InvocationHandler {

    private Object target;

     public RealHandler(Object target){
         super();
         this.target = target;
     }

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

         method.invoke(target, args);

        doAfter() ;
        return null;
    }

    //其实我希望 在这个方法 可以获取参数
    private void doBefore() {
        System.out.println("before method invoke");
    }

    private void doAfter() {
        System.out.println("after method invoke");
    }
}
package com.csair.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MainTest {

     public static void main(String[] args) {
            RealObject real=new RealObjectI();


            InvocationHandler handler=new RealHandler(real);

            //创建动态代理对象
            RealObject proxy=(RealObject)Proxy.newProxyInstance(
                    real.getClass().getClassLoader(), 
                    real.getClass().getInterfaces(), 
                    handler);


            proxy.realMethod("say :helloword");
        }
}
    原文作者:AOP
    原文地址: https://blog.csdn.net/chao_19/article/details/51824669
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞