手记

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

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;
}

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

下一章

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

4人推荐
随时随地看视频
慕课网APP