详解使用Java原生代理实现AOP实例

一说到AOP,大家一定会想到spring,因为这东西实在是太强大了.但是大家一定要清楚,AOP是一只编程思想,而Spring仅仅是AOP的一种实现罢了.

首先百度下:

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

今天呢,咱们就一起用Java原生代理实现简单的AOP功能.

首先,你得需要了解基本的反射知识,否则可能会感到困惑.

不罗嗦了,直接开始撸码

首先,咱们先写一个简单的接口.名字叫AnimalInterface,用来声明规范动物的一些基本方法.

这些方法包括 设置名字,获取名字,叫声,属性(原谅我没文化,其实就是获得是陆栖还是水栖或者水陆两栖)

package proxy.imp;
public interface AnimalInterface {
  //设置名字
  void setName(String name);
  //获取名字
  String getName();
  //叫声
  void say();
  //获取栖性
  void getProperty();
}

然后咱们实现这个接口,创建一个名叫小黑的Dog

package proxy;

import proxy.imp.AnimalInterface;
public class DogImp implements AnimalInterface {
  private String name = "小黑";
  public DogImp() {
  }
  @Override
  public void setName(String name) {
    this.name = name;
  }
  @Override
  public String getName() {
    return this.name;
  }
  @Override
  public void say() {
    System.out.println("小狗:汪汪汪汪.....");
  }
  @Override
  public void getProperty() {
    System.out.println("小狗是陆地动物,但是会游泳哦");
  }
}

大家一定迫不及待了,怎么实现类似AOP的功能呢….

咱们先创建一个名为AOPHandle的类,让其实现InvocationHandler接口,不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象,这种代理机制是面向接口,而不是面向类的,如果使用proxy,会造成无限递归.然后就是栈溢出,但是依旧能反射成功一次,这说明代理对象和对象的代理是不一样的,但是咱们可以通过proxy参数的proxy.getClass()获得class对象,然后获得被代理类的方法和参数,这也为注解注入,特定方法注入,属性注入提供了一种实现途径吧,关于这个,咱们后面再说..

package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AOPHandle implements InvocationHandler{
  //保存对象
  private Object o;
  public AOPHandle(Object o) {
    this.o=o;
  }
  /**
   * 这个方法会自动调用,Java动态代理机制
   * 会传入下面是个参数
   * @param Object proxy 代理对象的接口,不同于对象
   * @param Method method 被调用方法
   * @param Object[] args 方法参数
   * 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象
   * 这种代理机制是面向接口,而不是面向类的
   **/
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //方法返回值
    Object ret=null;
    //打印方法名称
    System.err.println("执行方法:"+method.getName()+"n参数类型为:");
    //打印参数
    for(Class type:method.getParameterTypes())
      System.err.println(type.getName());
    //打印返回类型
    System.err.println("返回数据类型:"+method.getReturnType().getName());
    //反射调用方法
    ret=method.invoke(o, args);
    //声明结束
    System.err.println("方法执行结束");
    //返回反射调用方法的返回值
    return ret;
  }
}

动态代理已经搞定..然后就是咱们的AnimalFactory了..咱们继续

package proxy;
import java.lang.reflect.Proxy;
public class AnimalFactory {
  /***
   * 获取对象方法
   * @param obj
   * @return
   */
  private static Object getAnimalBase(Object obj){
    //获取代理对象
    return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
        obj.getClass().getInterfaces(), new AOPHandle(obj));
  }
  /***
   * 获取对象方法
   * @param obj
   * @return
   */
  @SuppressWarnings("unchecked")
  public static T getAnimal(Object obj){
    return (T) getAnimalBase(obj);
  }
  /***
   * 获取对象方法
   * @param className
   * @return
   */
  @SuppressWarnings("unchecked")
  public static  T getAnimal(String className){
    Object obj=null;
    try {
      obj= getAnimalBase(Class.forName(className).newInstance());
    } catch (Exception e) {
      e.printStackTrace();
    }
    return (T)obj;
  }
  /***
   * 获取对象方法
   * @param clz
   * @return
   */
  @SuppressWarnings("unchecked")
  public static  T getAnimal(Class clz){
    Object obj=null;
    try {
      obj= getAnimalBase(clz.newInstance());
    } catch (Exception e) {
      e.printStackTrace();
    }
    return (T)obj;
  }
}

终于到最后了…还差什么呢,大家来这里看看效果吧…

哈哈…小二,上个菜..哦~不对,是个测试类..哈哈////

package proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.AnimalFactory;
import proxy.imp.AnimalInterface;

@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {

  @Test
  public void Test1() {
    AnimalInterface dog=AnimalFactory.getAnimal(DogImp.class);
    dog.say();
    System.out.println("我的名字是"+dog.getName());
    dog.setName("二狗子");
    System.out.println("我的名字是"+dog.getName());
  }
}

啥?什么,,到了最后说,,这又卵用,这不是坑爹么?就捕获一个这个玩意,什么用啊…

什么AOP,我怎么一点AOP的影子都没有看到,怎么切入自定义方法,就一个syso输入,往这忽悠观众来了?…..

好吧,那咱们继续…看看如何实现注入自定义方法…

首先增加一个接口,咱们就称为AOP注入接口吧.取名AOPMethod哈

创建after和before方法,接收Object proxy, Method method, Object[] args参数

这样就能做更多的事情叻…比如执行方法前,记录类状态,写入log.监控xx变量,,,

开启你的脑洞吧.

package proxy.imp;
import java.lang.reflect.Method;

public interface AOPMethod{
  //实例方法执行前执行的方法
  void after(Object proxy, Method method, Object[] args);
  //实例方法执行后执行的方法
  void before(Object proxy, Method method, Object[] args);
}

然后修改AOPHandle类,增加AOPMethod属性.

在修改构造方法,让在类初始化时获得AOPMethod实例.

最后修改invoke方法….直接上代码哈

package proxy;

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

import proxy.imp.AOPMethod;

public class AOPHandle implements InvocationHandler{
  //保存对象
  private AOPMethod method;
  private Object o;
  public AOPHandle(Object o,AOPMethod method) {
    this.o=o;
    this.method=method;
  }
  /**
   * 这个方法会自动调用,Java动态代理机制
   * 会传入下面是个参数
   * @param Object proxy 代理对象的接口,不同于对象
   * @param Method method 被调用方法
   * @param Object[] args 方法参数
   * 不能使用invoke时使用proxy作为反射参数时,因为代理对象的接口,不同于对象
   * 这种代理机制是面向接口,而不是面向类的
   **/
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object ret=null;
    //修改的地方在这里哦
    this.method.before(proxy, method, args);
    ret=method.invoke(o, args);
    //修改的地方在这里哦
    this.method.after(proxy, method, args);
    return ret;
  }
}

呼呼,大功告成,,看起来一切都么问题,萌萌哒..

赶紧更新下测试类…

package proxy;

import java.lang.reflect.Method;

import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.imp.AOPMethod;
import proxy.imp.AnimalInterface;

@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {

  public static void main(String[] args) {

    AnimalInterface dog = AnimalFactory.getAnimal(DogImp.class, new AOPMethod() {
      // 这里写方法执行前的AOP切入方法
      public void before(Object proxy, Method method, Object[] args) {
        System.err.println("我在" + method.getName() + "方法执行前执行");
      }

      // 这里系方法执行后的AOP切入方法
      public void after(Object proxy, Method method, Object[] args) {
        System.err.println("我在 " + method.getName() + "方法执行后执行");

      }
    });
    dog.say();
    String name1="我的名字是" + dog.getName();
    System.out.println(name1);
    dog.setName("二狗子");
    String name2="我的名字是"+dog.getName();
    System.out.println(name2);
  }
}

呼呼,亲们,是不是有注入的感觉了?是不是感觉把自己的方法切进去了???哈哈….

看起来一切都已经完美了,但是总觉得差了点什么?哦,对,缺少了类似于Spring那么样的配置文件..

其实那些已经很简单了,交给你们去做吧,设计好XML格式化就妥了,等等,你说什么,还不能拦截自定义方法?

不能像Spring那样拦截自定义方法?oh~~NO,其实已经可以了在before(Object proxy, Method method, Object[] args)中利用method和的给methodName就能做判断了.

当然,本例的并没有什么实用意义,更不能个各种完善的AOP框架相比,本文仅仅为您提供一种思路,但是一定要记住,再牛的东西也是一点点积累出来的

实例下载:http://xiazai.jb51.net/201701/yuanma/JavaAOP_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 举例讲解Java的Spring框架中AOP程序设计方式的使用

    1.什么是AOP AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续. 2.关于Spring AOP的一些术语:  A.切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现 B.连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行 C.通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作.

  • Java的Spring框架中AOP项目的一般配置和部署教程

    0.关于AOP 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP是OOP的延续. 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. 主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过

  • 详解Java反射实现Aop代理

    利用反射生成JDK的动态代理,也就是AOP中的AOP代理,代替目标对象,从而在代码中织入增强. 定义代理接口 由于JDKf动态代理只能为接口创建动态代理,故先定义接口,假定我们需要对数据的Save方法添加事务处理,我们有一个UserDao接口,里面有一个Save方法,代码如下: public interface UserDao { public void save(); } 定义代理实现 下面具体来实现接口定义的Save方法,我们采用下面的代码来实现. public class UserDaoI

  • java基于spring注解AOP的异常处理的方法

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的. 二.基于@ControllerAdvice(加强的控制器)的异常处理 @ControllerAdvice注解内部使用@Except

  • Java动态代理实现AOP

    目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至,也涌现出大量支持AOP的优秀Framework,--Spring, JAC, Jboss AOP 等等.AOP似乎一时之间成了潮流.Java初学者不禁要发出感慨,OOP还没有学通呢,又来AOP.本文不是要在理论上具体阐述何为AOP, 为何要进行AOP . 要详细了解学习AOP可以到它老家http://aosd.net去瞧瞧.这里只是意图通过一个简单的例子向初学者展示一下如何来进行AOP. 为了简单起见,例子

  • 实例讲解Java的Spring框架中的AOP实现

    简介 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足. 除了类(classes)以外,AOP提供了 切面.切面对关注点进行模块化,例如横切多个类型和对象的事务管理. (这些关注点术语通常称作 横切(crosscutting) 关注点.) Spring的一个关键的组件就是 AOP框架. 尽管如此,Spring IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring IoC容器更加完善

  • Java的Spring框架下的AOP编程模式示例

    Spring框架的关键组件是面向方面编程(AOP)框架.面向方面的编程不仅打破程序逻辑分成不同的部分称为所谓的担忧.跨越多个点的应用程序的功能被称为横切关注点和这些横切关注点是从应用程序的业务逻辑概念上区分开来.还有像日志记录,审计,声明性事务,安全性和高速缓存等方面的各种常见的好例子 模块化的OOP中的关键单元是类,而在AOP中模块化的单元则是切面.依赖注入可以帮助你从对方解耦应用程序对象和AOP可以帮助你从他们影响的对象分离横切关注点. AOP是一样的编程语言如Perl,.NET,Java和

  • Java实现AOP面向切面编程的实例教程

    介绍 众所周知,AOP(面向切面编程)是Spring框架的特色功能之一.通过设置横切关注点(cross cutting concerns),AOP提供了极高的扩展性.那AOP在Spring中是怎样运作的呢?当你只能使用core java,却需要AOP技术时,这个问题的解答变得极为关键.不仅如此,在高级技术岗位的面试中,此类问题也常作为考题出现.这不,我的朋友最近参加了一个面试,就被问到了这样一个棘手的问题--如何在不使用Spring及相关库,只用core Java的条件下实现AOP.因此,我将在

  • Java AOP知识详细介绍

    Java AOP AOP知识整理 AOP(Aspect-Oriented Programming):面向切面的编程.OOP(Object-Oriented Programming)面向对象的编程.对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其实AOP是对OOP的一种补充,OOP面向的是纵向编程,继承.封装.多态是其三大特性,而AOP是面向横向的编程. 面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足.在OOP中模块化的关键单元

  • Java之Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就算这样,但你肯定也会有后台管理及登录功能. 每个项目中都会有这些几乎一样的业务逻辑,我们能不能把他们做成通用的系统呢? AOP 实现用户权限验证 AOP 在实际项目中运用的场景主要有权限管理(Authority Management).事务管理(Transaction Management).安全管

随机推荐