对AOP切面的一些整理与理解

  首先上一张AOP的图示

一:几个重要的概念

  1> 切面:横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象[验证切面。日志切面]

  2> 通知:切面中的每个方法

  3> 目标:被通知的方法(业务逻辑中的方法)

  4> 代理(proxy):向目标对象应用通知之后创建的对象

  5> 连接点:程序运行前的某个特定位置(详细的物理存在):如某个方法调用前,调用后,方法抛出异常后等。

连接点由两个信息确定:方法表示的程序运行点相对点表示的方位。

  6> 切点:每一个类会有多个连接点(看不到摸不到,非详细物理存在)[通过切点能够定位到非常多个连接点]即:连接点是程序类中客观存在的事务。

AOP通过切点定位到特定的链接点。

类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一一相应的关系,一个切点匹配多个连接点。切点通过接口进行描写叙述。使用类和方法作为连接点的查询条件。

二:Spring AOP

  1)增加jar包

  2)在配置文件里增加aop的命名空间(namespace),完整命名空间例如以下:

    <?xml version="1.0" encoding="GB18030"?

>

    <beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans                               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                               http://www.springframework.org/schema/aop                               http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    </beans>

  3)基于注解的方式

     1.在配置文件里增加该配置

     <!-- 启动用JDK动态代理完毕对Aop的支持,支持注解的形式 -->

     <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

     

     2.配置切面及业务逻辑对象  

     但在 spring4.0 能够配置自己主动扫描的包。仅仅须要包命明白就可以

     <context:component-scan   base-package="" />

    

     spring2.0不具备该属性。正确配置例如以下:1》切面 2》业务逻辑对象

     <!-- 切面 -->

     <bean id="checkAspect" class="com.inspur.aop.impl.CheckAspect"></bean>

     <!-- 业务逻辑对象 -->

     <bean id="calculator"  class="com.inspur.aop.impl.CalculatorLightImpl"> 

     </bean> 

     3.通过代码进行展示 testspring2

    package com.inspur.aop.impl;

    import java.util.Arrays;

    import java.util.List;

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.annotation.Before;

    import org.aspectj.lang.annotation.Pointcut;

    @Aspect

    public class CheckAspect {

         /**

          * 切入点 做标识使用 特征:private void 方法名(){ }

          */

         @Pointcut("execution(* com.inspur.aop.impl.*.*(..))")

         public void allCalMethod() {}

         @Before("allCalMethod()")

         public void check(JoinPoint joinPoint) {

          //两种方法获取參数的值

          /*// 取得參数的值

             Object[] objects = joinPoint.getArgs();

             if (objects != null && objects.length > 0) {

                 for (Object arg : objects) {

                     System.out.println(arg);

                 }

          }*/

           String methodName = joinPoint.getSignature().getName();

           System.out.println(" methodName " + methodName);

           List<Object> args = Arrays.asList(joinPoint.getArgs());

           System.out.println(" the method " + methodName + " begin with " + args);

        }

    }

    

    另:切入点事实上能够不进行书写,仅作为标识使用。

        如不写,则在通知(@befor,@after等)中写进运行语句

            即@Before("execution(* com.inspur.aop.impl.*.*(..))")

        也能够实现作为切面的功能。

面向切面编程是面向对象编程的一种改进。他的出如今于解决两大问题:(详见testSpring2项目)

  1.代码混乱:越来越多的非业务需求(日志和校验等)增加后,原有的业务方法急剧膨胀, 每一个方法在处理核心业务逻辑时,还必须兼顾其它多个关注点。

  2.代码分散:以日志需求为例。仅仅是为了满足这个单一的需求,就不得不在多个模块 里面多次反复同样的日志代码。

假设日志代码发生改变,也必须改动全部模板。[核心代码须要写入众多的输出语句,代码冗余及维护困难等各种问题]

从上述代码引申三个问题:

1.切入点的定义[execution:运行]

·随意公共方法的运行

  execution(public * *(..))

·随意一个以‘set’開始的方法的运行

  execution(* set*(..))

·AccountService接口的随意方法的运行

execution(* com.xyz.service.AccountService.(..))

·定义在service包里随意方法的运行(最为经常使用)

  execution(* com.xyz.service.*.*(..))

·定义在service包或子包里随意方法的运行

 )

2.Adivce。通知的类型

 ·前置通知 @Before

 ·后置通知 @After

 ·返回后通知

 ·异常抛出后通知

 ·围绕通知

3.JoiPoint方法:不论什么一个增强方法都能够通过将第一个入參声明为 JoinPoint
訪问到连接点上下文的信息。(简化日志)

  AspectJ 使用 org.aspectj.lang.JoinPoint 接口表示目标类连接点对象。假设是围绕增强时,使用org.aspectj.lang.ProceedingJoinPoint
表示连接点对象,该类是 JoinPoint 的子接口。

不论什么一个增强方法都能够通过将第一个入參声明为 JoinPoint 訪问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:

1) JoinPoint

? java.lang.Object[] getArgs():获取连接点方法执行时的入參列表。

? Signature getSignature() :获取连接点的方法签名对象。

? java.lang.Object getTarget() :获取连接点所在的目标对象;

? java.lang.Object getThis() :获代替理对象本身;

2) ProceedingJoinPoint

ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于运行连接点方法的方法:

? java.lang.Object proceed() throws java.lang.Throwable:通过反射运行目标对象的连接点处的方法;

? java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射运行目标对象连接点处的方法,只是使用新的入參替换原来的入參。

  上面的代码提到了两种获取參数的方法。重点记住各个方法的类型及遍历的方式。

时间: 2024-12-17 05:00:14

对AOP切面的一些整理与理解的相关文章

spring AOP切面日志 拦截方法中有同名方法问题

代码: @ResponseBody @RequestMapping("/login.do") public Json login(SysUserPM sysUserPM, HttpSession session) { Json j = new Json(); SysUserPM sysUser = sysUserServiceI.doLogin(sysUserPM); if (sysUser != null) { System.out.println("后台用户登录成功!&q

动态代理和AOP切面编程

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* * 动态代理和AOP切面编程 */ //定义一个接口 interface Person { void eat(); void breath(); } // 定义一个实现接口的实现类,即为被代理类 class Student implements Person { @Overr

使用Spring AOP切面解决数据库读写分离

http://blog.jobbole.com/103496/ 为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如何做到把数据写到master库,而读取数据的时候,从slave库读取.如果应用程序判断失误,把数据写入到slave库,会给系统造成致命的打击. 解决读写分离的方案很多,常用的有SQL解析.动态设置数据源.SQL解析主要是通过分析sql语句是insert/select/update/delete中的哪

AOP基础知识及AOP切面编程之注释方法、xml配置方法

<span style="font-family: 微软雅黑; font-size: 10.5pt; letter-spacing: 0pt; ">AOP概念</span> Aspect(切面):它跟类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是对横切性关注点的抽象 joinpoint(连接点):所谓连接点就是被拦截到的点,在spring中,这些点是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器

AspectJ AOP切面编程(XML配置)

1. AspectJ支持通知类型 (6种) Before 前置通知,相当于BeforeAdvice AfterReturning 后置通知,相当于AfterReturningAdvice Around 环绕通知,相当于MethodInterceptor AfterThrowing抛出通知,相当于ThrowAdvice After 最终final通知,不管是否异常,该通知都会执行 DeclareParents 引介通知,相当于IntroductionInterceptor 2. advisor和

AOP切面编程

AOP的实现底层实际上即为反射,JDK中的反射类java.lang.reflect.Proxy是Java中唯一可以访问调度器的类.类似地,常见的动态代理库cglib也是通过反射机制实现了动态代理的封装.技术成熟度相对较高的AspectJ和Spring AOP会在底层实现一套reflect机制,区别是两者对规范实现如何定义而已. 无论是AspectJ还是Spring AOP,所有这些AOP编程都是基于反射和运行时的动态代理控制实现的.下面通过Proxy和Cglib来实现自己的动态代理切面. 假设我

Spring AOP 切面编程记录日志和接口执行时间

最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特别长.知道了问题之后,就需要对查询比较慢的接口进行优化,但哪些接口需要优化.哪些不需要呢?只能通过日志里的执行时间来判断,那么如何才能知道每一个接口的执行时间呢? 如果想学习Java工程化.高性能及分布式.深入浅出.微服务.Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级

SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部

SPRING学习(十九)--基于注解的AOP切面编程

上篇中介绍了基于XML配置的AOP切面编程,除了XML配置AOP切面编程外,还可以通过注解方式实现AOP切面编程,本篇通过一个小例子来介绍基于注解的AOP编程. 1.在spring中使用AOP变成,不止要导入spring-aop.jar,还需要导入spring-aspects.jar.aspectjweaver.jar和aopalliance.jar,但是aspectjweaver.jar被spring-aspects.jar依赖,aopalliance.jar被spring-aop.jar依赖