首页 > 开发 > JAVA > 正文

【自定义框架系列】【InvocationHandler】java AOP反射代理机制

2016-04-19 12:13:05  来源:慕课网

java中的AOP [Aspect Oriented Programming] 代理,本章需要对java中的【反射机制】有所了解。否则听起来可能似懂非懂的样子。

java中有自己的原生代理。在学习代理之前需要明白什么是代理。 假如方法的执行到得到返回值比喻成 电源 --- 电灯,那么代理就是开关。
在一般理解中 代理就是 目的出发点到目的结束点中间的非直接内容过程大概可以描述为

                        |----V----|            电源【方法】 --------- 开关【代理】 ---------电灯【返回值】

在没有代理的时候应该是

电源【方法】 ---------电灯【返回值】

中间的代理层环节就是我们需要理解的部分。一般,使用代理的时候都是在事务控制,权限控制上。 我们需要事务的一致性来保证数据库数据完整性,我们需要根据不同的角色界定不同的权限。事实上,这些东西完全可以用手动来控制,但是,在多数情况下,我们需要控制的事务、角色太多,就会偏离了我们本来应该关心的方面。

以上皆为扯淡,以下为正文

现在我们来实现代理过程
要实现代理,那么最好是面向接口的编程。

public interface User{        /**添加增加user的方法*/       public boolean addUser(String userName,String pass);}

创建的接口,接下来就是写它的实现类

public class UserImpl implements User {      private Map<String,String> userMap = new HashMap<>();      public UserImpl () { /*something*/}      @Override      public boolean addUser(String userName,String pass){        boolean hasOne=   userMap.containsKey(userName);        if(!hasOne){                userMap .put(userName,pass);                return true;        }        return false;    }}

接下来就是实现代理接口【java.lang.reflect.InvocationHandler

public class UserProxy implements InvocationHandler {    private Object targetObject;//接受代理对象    public UserProxy(Object targetObject){        this.targetObject =targetObject;    }    /**复写代理接口调用方法     *@param proxy  代理对象     *@param  method   目标方法     *@param  args  目标方法参数     *@return  Object   目标方法返回值     */    @Override    public Object invoke(Object proxy, Method method, Object[] args){        User user = (UserImpl)targetObject;//将传入的对象转成需要的对象        /*         *method【当前方法】         *method.invoke(targetObject【目标对象这里的就是User 】,args【方法参数】)         */        Object result=method.invoke(targetObject, args);//调用method的反射方法执行         return result;      }}

实现了接口代理之后,我们就来测试一下,我们使用【java.lang.reflect.Proxy】来生成代理对象,传入类加载器,类的接口对象,代理对象

public class UserProxyEXEC {    public static void main(String[] arges){        User user = new UserImpl();        UserProxy proxy = new UserProxy(user);        User u = (User) Proxy.newProxyInstance(                user.getClass().getClassLoader(), user.getClass()                        .getInterfaces(), proxy);       boolean bool = u.addUser("zhangsan", "lisi");       System.out.println(bool);    }}

现在我们需要对原来的代理方法进行扩展,让他指定如果当前第一个参数userName是admin,就不让他添入。

     @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        User user = (UserImpl)targetObject;        Object result =null;        for (int i = 0; i < args.length; i++) {            if(args[i] == null||"".equals(args[i])){                 System.out.println("第"+(i+1)+"个参数为null");                return false;}            if(args[0] instanceof String){                if("admin".equalsIgnoreCase((String)args[i])){                    return false;                }            }        }      result=method.invoke(targetObject, args);      return result;}

将当前的传入参数控制一下,就可以完成对方法的控制了,是不是很简单!

下一章

将前两章内容结合一下,使用注解+代理的方式,来实现注解对方法的控制