当前位置:首页 > 编程教程 > java技术文章 > java AOP原理以及实例用法总结

实例分享java AOP原理及用法

  • 发布时间:
  • 作者:码农之家
  • 点击:107

这篇文章主要知识点是关于java、AOP、的内容,如果大家想对相关知识点有系统深入的学习,可以参阅以下电子书

Java虚拟机基础教程
  • 类型:java大小:78.6 MB格式:PDF作者:文森特·范德利昂
立即下载

java AOP原理以及实例用法总结

AOP :

面向切面编程

在程序设计中,我们需要满足高耦合低内聚,所以编程需满足六大原则,一个法则.

AOP面向切面编程正是为了满足这些原则的一种编程思想.

一.装饰者模式:

当我们需要给对象增加功能时,为了满足单一职责原则,可利用装饰者模式编程,创建一个类用来装饰原来的类,这个类写需要在原来的功能上增加的功能.

比如:一个类里面有一个增加图书的功能,

@Service
public class BookSericeImpl implements BookSerice {
 @Override
 public void addOne(BokBean bokBean) {
  System.out.println("执行逻辑:插入一本书");
 }
 @Override
 public void deletOne(Long bookId) {
  System.out.println("执行逻辑:删除一本书");
 }
}

我们需要在这个基础上新增打印日志的功能,

public class BooklogServiceImpl implements BookSerice {
 private BookSerice bookSerice;
 public BooklogServiceImpl(BookSerice bookSerice) {
  this.bookSerice = bookSerice;
 }
 @Override
 public void addOne(BokBean bokBean) {

  System.out.println("准备新增一本书");
  this.bookSerice.addOne(bokBean);
  System.out.println("新增一本书完成");
 }
 @Override
 public void deletOne(Long bookId) {

  System.out.println("准备删除一本书");
  this.bookSerice.deletOne(323L);
  System.out.println("删除一本书完成");
 }
}

下面我们调用这个增强过后的的对象

public void test1(){

  //Aop :面向切面编程

  //使用装饰者模式设计对象
  BookSerice bookSerice = new BookSericeImpl();
  //把原来功能的对象通过构造方传给新增功能的类,并把新增功能类的对象赋给原来对象
  //这里新增功能类和原来的类都是实现了同一个接口.
  bookSerice = new BooklogServiceImpl(bookSerice);
  //调用新增功能类的方法,在这个方法里让构造方法传过去的对象调用原来的功能
  bookSerice.addOne(new BokBean());
 }

这样我们就在不改变原来代码的基础上新增了功能,并且也满足单一职责的原则,降低了代码的耦合性.

但是如果接口里面有很多方法,如果每个方法都需要增加日志功能,这样就会出现很多重复代码,并且装饰者模式不能同时为多个没有关系的类同时增强

所以java引入动态代理技术来增加功能.

二.动态代理

在java里动态代理有两个实现方式:

①针对有接口的类的代理,使用jdk中反射包下的动态代理

②针对没有接口的类的代理,使用第三方的jar包Enhancer

如果一个类既没有接口,又是final,那么不能进行增强

1.第一种实现:

基于接口的动态代理,使用java内部反射包增强

这种方式创建对象是目标对象的兄弟对象.

同样上面是实现了接口的两个功能的类:

@Service
public class BookSericeImpl implements BookSerice {
 @Override
 public void addOne(BokBean bokBean) {
  System.out.println("执行逻辑:插入一本书");
 }
 @Override
 public void deletOne(Long bookId) {
  System.out.println("执行逻辑:删除一本书");
 }
}

调用通过对象调用上面两个方法:

public void test2(){

 //创建需要代理的对象
 BookSerice bookSerice = new BookSericeImpl();
 //根据对象的类获取类加载器
 ClassLoader classLoader = bookSerice.getClass().getClassLoader();
 //获取被代理对象说实现的所有接口
 Class<?>[] interfaces = bookSerice.getClass().getInterfaces();
 //新建代理对象,里面参数需要(类加载器,一个对象所实现的接口,InvocationHandler接口类的对象)
 bookSerice = (BookSerice) Proxy.newProxyInstance(classLoader, interfaces, new LogHandler(bookSerice)); 
 bookSerice.addOne(new BokBean());
 bookSerice.deletOne(232L);
}

在创建代理对象的时候需要一个InvocationHandler接口类的对象,下面创建一个该类的实现类

public class LogHandler implements InvocationHandler {

 //通过构造方法接受一个没有被代理的原来的对象
 //通过下面的方法名的反射找到这个对象对应方法
 private Object target;
 public LogHandler(Object target) {
  this.target = target;
 }
 //当代理对象调用原方法的时候,就会调用这个invoke方法
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  String classname = target.getClass().getName();
  String methodName = method.getName();
  System.out.println(classname+"."+methodName+"方法开始执行");
  //这里实际是Method类通过方法名反射调用了原方法(addone)
  Object value = method.invoke(target, args);
  System.out.println(classname+"."+methodName+"方法执行完毕");
  return value;

 }
}

这样实现了动态代理之后,不管实现的接口里有多少个方法,你只需调用该方法,就会增强该方法,而不需要针对每个方法写一遍增强功能,

并且这个增强类LogHandler类和原来的实现类BookSericeImpl类并没有耦合性,这就是说不管你是什么接口类的实现类,只需要对该类的对象进行代理即可,就能对该类的方法添加上这个新增的功能

总的来说,这种动态代理实现方式就是利用反射技术,找到调用的方法名,针对这个方法进行增强.

如果当不需要对某方法增加功能时,就不用不带.

2.第二种实现:

基于类的动态代理,使用cglib框架.
这种方式创建的代理对象是目标对象的子类对象

第二种方式是利用第三方jar包来实现,下载CGLIB包:

java AOP原理以及实例用法总结

利用jar包中的Enhancer类创建增强对象.

创建增强对象需要根据原对象的类名创建类增强器,还需要根据原对象的类型创建子类代理对象

属性通过增强对象set方法赋值,上一种方式是通过调用方法Proxy.newProxyInstance传参.

public void test3(){

  //创建需要代理增强的对象
  BookSerice bookSerice = new BookSericeImpl();
  Enhancer enhancer = new Enhancer();
  //用增强器对象创建类增强器
  enhancer.setClassLoader(bookSerice.getClass().getClassLoader());

  //因为创建的代理对象是目标对象的子类,所以这里填的就是目标对象的类
  enhancer.setSuperclass(bookSerice.getClass());

  //创建代理对象,这里需要的参数是Callback接口的对象,所以需要创建一个接口的实现类.
  enhancer.setCallback(new TimeMethodInterceptor(bookSerice));
  //把代理对象赋给原对象
  bookSerice = (BookSerice) enhancer.create();
  bookSerice.addOne(new BokBean());
  bookSerice.deletOne(1l);
  
 }

创建Callback接口的实现类,也就是功能增强部分,

这一部分跟第一种方式的实现是一样的,都是通过反射在添加功能过程中调用原方法.

//Callback接口没有实现方法,所以这里实现的是他的子接口
public class TimeMethodInterceptor implements MethodInterceptor {

 private Object target;

 public TimeMethodInterceptor(Object target) {
  this.target = target;
 }

 @Override
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  //记录当前系统时间
  //这个时间是从1970年1月1日 0点0分到现在的毫秒数
  long start = System.currentTimeMillis();
  Object value = method.invoke(target, objects);
  long time = System.currentTimeMillis() - start;
  System.out.println("当前时长"+time+"毫秒");
  return null;
 }
}

总结:

两种方法的区别:

第一种是用jdk内部方法创建代理对象,由于创建过程中需要一个对象的接口,所以只能针对有接口类的对象进行代理.

第二种是利用第三方jar包中的增强器(Enhancer)创建代理对象,通过set方法给需要的属性赋值.由于没有接口实现,所以创建的是对象的子类代理对象.

以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。

Java 相关电子书
学习笔记
网友NO.945068

新手快速入门JavaScript装饰者模式与AOP

什么是装饰者模式 当我们拍了一张照片准备发朋友圈时,许多小伙伴会选择给照片加上滤镜。同一张照片、不同的滤镜组合起来就会有不同的体验。这里实际上就应用了装饰者模式:是通过滤镜装饰了照片。在不改变对象(照片)的情况下动态的为其添加功能(滤镜)。 需要注意的是:由于 JavaScript 语言动态的特性,我们很容易就能改变某个对象(JavaScript 中函数是一等公民)。但是我们要尽量避免直接改写某个函数,这会导致代码的可维护性、可扩展性变差,甚至会污染其他业务。 什么是 AOP 想必大家对"餐前洗手、饭后漱口"都不陌生。这句标语其实就是 AOP 在生活中的例子:吃饭这个动作相当于切点,我们可以在这个切点前、后插入其它如洗手等动作。 AOP(Aspect-Oriented Programming):面向切面编程,是对 OOP 的补充。利用AOP可以对业务逻辑的各个部……

网友NO.962672

Java实现AOP功能的封装与配置的小框架实例代码

本文通过是动态代理实现的AOP功能的封装与配置的小框架.加深对动态代理和AOP编程的理解 设计 根据配置文件的键xxx对应的值(类全名)创建相应类的对象。 当且仅当xxx对应的值为 com.iot.proxy.aopframework.ProxyFactoryBean 时,则生成相应的动态代理类对象。代理对象的目标类和通知实现类分别由 xxx.target 和 xxx.advice 配置 配置文件 config.propertiest 位于aopframework包下 xxx代表要加载的类 xxx.advice代表通知接口的某个实现类 xxx.target代表委托类 #xxx=java.util.ArrayList xxx=com.iot.proxy.aopframework.ProxyFactoryBean xxx.advice=com.iot.proxy.MyAdvice xxx.target=java.util.ArrayList 包: com.iot.proxy.aopframework ,有如下几个类/接口: BeanFactory,用于读取配置文件,根据配置创建相应的对象 ProxyFactoryBean,用于生成代理对象,含有两个私有属性:目标和通知 Advice,通知接口,用于把切面的代码以对象的形式传递给In……

<
1
>

Copyright 2018-2020 www.xz577.com 码农之家

版权投诉 / 书籍推广 / 赞助:520161757@qq.com