AOP技术,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

1、切面(Aspect)

一个服务层方法增强的一类功能点,一类功能实现就是切面,里面可以定义多个advice

事务管理、日志管理、异常控制 : 都是切面

2、连接点(Joinpoint)

就是对应的具体的被代理的方法 : execute()

Joinpoint跟我们具体的被代理的方法一一对应

3、切点(Pointcut)

可以认为是连接点(joinpoint的集合,是很多方法的集合

4、增强\通知(Advice)

所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

5、Advisor

advice和pointcut的组合或封装,Advisor可以认为它是一个只有一个advice的切面

6、引入(Introduction)

实际上也是一个类的扩展,可以认为往这个被代理类中加入动态方法

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。

一、aop的xml配置元素

<aop:pointcut>:用来定义切入点,该切入点可以重用; 
<aop:advisor>:用来定义只有一个通知和一个切入点的切面; 


//下面是另外一种定义方式 如上图  用的比较多的是上面那种定义方式,例如tx(事物通知)
<aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的通知和切入点定义是无序的;
        和advisor的区别就在此,advisor只包含一个通知和一个切入点。

第二种方式例子:

package com.dongnao.jack.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class AopAspectj {

    public void before() {
        System.out.println("开启事务");
    }

    public void after() {
        System.out.println("关闭事务");
    }

    public void afterReturning() {
        System.out.println("返回后通知");
    }

    public void afterthrowing() {
        System.out.println("抛出后通知");
    }

    public void around(ProceedingJoinPoint point) {
        System.out.println("前置环绕通知");
        try {
            point.proceed();
        }
        catch (Throwable e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("后置环绕通知");
    }
}
<bean id="myaspectj" class="com.dongnao.jack.aop.AopAspectj"></bean>

<aop:config>
    <aop:aspect id="txAspect" ref="myaspectj" order="2">
        <!-- 在此处定义的pointcut是全局的pointcut只供当前的aspect使用 id:表示这个pointcut的名称,以方便使用 -->
        <aop:pointcut id="myMethod2" expression="execution(public * com.dongnao.jack.service..*.*(..))" />
        <!-- 定义advice时的参数
            method:切面逻辑的方法名称(切面类中的方法名)
            pointcut-ref:表示引用哪个pointcut(要求已经在上面定义好了)
            pointcut:定义一个pointcut    -->
            <!--
            <aop:before method="before" pointcut-ref="myMethods"/>
            <aop:after-returning method="afterReturning" pointcut="execution(public * com.dongnao.jack.service..*.*(..))"/>
            <aop:after method="after" pointcut-ref="myMethod2"/>
            <aop:after-throwing method="afterthrowing" pointcut-ref="myMethods"/>
            <aop:around method="around" pointcut-ref="myMethod2"/>
            <aop:before method="before" pointcut="execution(public * com.dongnao.jack.aop..*.*(..))"/>
            -->
            下面第一行是自己定义切点,第二行用公用切点,通知方法用的切面定义的方法
            <aop:before method="before" pointcut="execution(public * com.dongnao.jack.service..*.*(..))"/>
            <aop:after method="after" pointcut-ref="myMethod2"/>

    </aop:aspect>
</aop:config>

第一种方式:也是我们常用的方式

自己定义的通知必须要实现MethodInterceptor

public class MyInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        Object result = invocation.proceed();
        return result;
    }

    private void before() {
        System.out.println("自定义MethodInterceptor前置增强");
    }
}
<bean id="myInterceptor" class="com.dongnao.jack.interceptor.MyInterceptor"></bean>

<aop:config>
    <aop:advisor advice-ref="myInterceptor" pointcut="execution(public * com.dongnao.jack.service..*.*(..))" order="1"/>
</aop:config>

二、引入的使用

<bean id="myintroduction" class="com.dongnao.jack.aop.IntroductionClass"></bean>
<aop:declare-parents types-matching="com.dongnao.jack.service.MyServiceImpl"
                implement-interface="com.dongnao.jack.aop.IntroductionIntf" 
                delegate-ref="myintroduction"/>

动态的将 MyServiceImpl 这个接口实现了IntroductionIntf 这个接口,里面的内容为myintroduction这个类实现类的内容

三、aop链式拦截器

自定义aop链式拦截器要实现MethodInterceptor这个接口

自定义请求响应拦截器实现HandlerInterceptor这个接口

results matching ""

    No results matching ""