手写AOP

来源:互联网 发布:电脑音频剪辑软件 编辑:程序博客网 时间:2024/05/22 02:15

一、我们首先看两个很重要的类/接口

1.InvocationHandler
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwableproxy:  指代我们所代理的那个真实对象method:  指代的是我们所要调用真实对象的某个方法的Method对象args:  指代的是调用真实对象某个方法时接受的参数

2.Proxy

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法

@CallerSensitive    public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h)        throws IllegalArgumentException      loader:  ClassLoader loader:它是类加载器类型,你不用去理睬它,你只需要知道怎么可以获得它就可以了:MyInterface.class.getClassLoader()就可以获取到ClassLoader对象,没错,只要你有一个Class对象就可以获取到ClassLoader对象;interfaces:指定newProxyInstance()方法返回的对象要实现哪些接口,没错,可以指定多个接口,例如上面例子只我们只指定了一个接口:Class[] cs = {MyInterface.class}; h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上  

二、手写AOP

1.具体业务代码:

package AOP3;public interface IHello {/**     * 业务方法     * @param str     */    void sayHello(String str);}

package AOP3;public class Hello implements IHello{@Overridepublic void sayHello(String str) {System.out.println("hello "+str);}}
2.代理代码

package AOP3;import java.lang.reflect.Method;public interface ILogger { void start(Method method); void end(Method method);}

package AOP3;import java.lang.reflect.Method;import java.util.Date;public class DLogger implements ILogger {@Overridepublic void start(Method method) {// TODO Auto-generated method stubSystem.out.println(new Date()+ method.getName() + " say hello start...");}@Overridepublic void end(Method method) {// TODO Auto-generated method stubSystem.out.println(new Date()+ method.getName() + " say hello end");}}

package AOP3;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class DynaProxyHello1 implements InvocationHandler{ //调用对象    private Object proxy;    //目标对象    private Object target;        public Object bind(Object target,Object proxy){        this.target=target;        this.proxy=proxy;        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this)    }            @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        Object result = null;        //反射得到操作者的实例        Class clazz = this.proxy.getClass();        //反射得到操作者的Start方法        Method start = clazz.getDeclaredMethod("start", new Class[]{Method.class});        //反射执行start方法        start.invoke(this.proxy, new Object[]{method});        //执行要处理对象的原本方法        method.invoke(this.target, args);        //反射得到操作者的end方法        Method end = clazz.getDeclaredMethod("end", new Class[]{Method.class});        //反射执行end方法        end.invoke(this.proxy, new Object[]{method});        return result;    }}

package AOP3;public class DynaTest1 { public static void main(String[] args) {        IHello hello = (IHello) new DynaProxyHello1().bind(new Hello(),new DLogger());//如果我们需要日志功能,则使用代理类        //IHello hello = new Hello();//如果我们不需要日志功能则使用目标类        hello.sayHello("明天");  //当调用了sayHello时就调用了DynaProxyHello1的invoke方法     }}



Sat Dec 02 20:48:19 CST 2017sayHello say hello start...hello 明天Sat Dec 02 20:48:19 CST 2017sayHello say hello end
 
原创粉丝点击