spring_aop

环境搭建

在导入ioc包基础上导入这几个包

com.springsource.net.sf.cglib-2.2.0.jar     动态代理包

com.springsource.org.apoaliance-1.0.0.jar  

com.springsource.org.aspectj.tools-1.6.6.RELEASE.jar

spring-aop-4.1.0.RELEASE.jar              面向切面编程提供AOP实现

spring-aspects-4.1.0.RELEASE.jar        与AspectJ框架的整合

头文件信息样式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

        <!--开启自动扫描-->
        <context:component-scan base-package="com.chinasofti"></context:component-scan>
        <!--spring中使用aspectj包中的@Aspect注解标注当前组件为切面
            如果要使用注解必须开启aspectj的自动代理模式-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

aop的核心组件:

Aspect(切面):切面是封装通用业务逻辑的组件,可以作用到其他组件上

Pointcut(切入点):用于指定哪些组件哪些方法使用切面组件,spring提供表达式来实现该指定

Advice(通知):用于指定组件作用到目标组件的具体位置

AOP前置通知:在目标组件的方法执行前执行的程序

步骤:切入点程序 —>切面程序—>通过配置文件将切面程序插入到切入点程序的某个位置上(通知)

切入点程序:可以是Spring组件中的任意方法

package com.chinasofti.bean;

public class Target {
    public String save(String name){
        System.out.println("目标函数执行");
        System.out.println(10/0);
        return "保存成功";
    }
}
 <bean id="target" class="com.chinasofti.bean.Target"></bean>

切面程序:是spring组件中的某个方法,无返回类型,参数类型与通知类型有关,前置通知的参数类型为org.aspectj.lang.JoinPoint(可以无参数)

package com.chinasofti.test3_1;


import org.aspectj.lang.JoinPoint;

public class TestBefore {
    public void doBefore(JoinPoint jp){
        System.out.println("获取目标函数参数" + jp.getArgs()[0]);
        System.out.println("获取目标函数所在对象" + jp.getTarget().getClass().getName());
        System.out.println("获取目标函数的java反射对象" + jp.getSignature());
        System.out.println("执行前置通知");
    }
}

配置aop前置通知 

    <bean id="testBefore" class="com.chinasofti.test3_1.TestBefore"></bean>
<aop:aspect>
<!--配置aop切入点:expression为切入点表达式,代表那些切入点程序执行时被插入切面程序-->
        <!--execution表达式中第一个* 代表什么返回类型都可以 第二个* 代表有无参数都可以-->
        <aop:pointcut id="targetPintcut" expression="execution(* com.chinasofti.bean.Target.save(*))" />
        <!--配置切面 ref:切面对象-->
        <aop:aspect ref="testBefore">
            <!--设定通知为前置
                method:切面的方法
                pointcut-ref:指定通知作用在那些切入点上-->
            <aop:before method="doBefore" pointcut-ref="targetPintcut" />
        </aop:aspect>

AOP后置通知 (只能包含2个参数)

AOP后置通知:在目标组件的方法正常执行并返回参数后执行的程序。

切面程序:后置通知的切面程序中可以获取到目标方法返回参数,单需要在配置文件中声明参数名,依赖spring容器注入参数值

package com.chinasofti.test3_1;

import org.aspectj.lang.JoinPoint;

public class TestAfterReturn {
    public void testAfterReturn(JoinPoint jp,Object oRet){
        System.out.println("目标函数的返回值:" + oRet);
        System.out.println("后置通知在目标函数正常执行并返回参数后执行");
    }
}
<aop:aspect ref="testAfterReturn">
            <!--设定通知为后置
                method:切面的方法
                pointcut-ref:指定通知作用在那些切入点上-->
            <aop:after-returning method="testAfterReturn" pointcut-ref="targetPintcut" returning="oRet"/>
        </aop:aspect>

AOP异常通知

AOP异常通知:在目标组件的方法抛出异常信息后执行的程序(只能包含2个参数)

切面编程:异常通知的切面程序中可以获取到目标组件抛出的异常信息,需要在配置文件上声明异常参数名(与后置通知很类似),依赖spring容器注入参数值

package com.chinasofti.test3_1;

import org.aspectj.lang.JoinPoint;

public class TestThrowing {
    public void doThrow(JoinPoint jp,Throwable e){
        System.out.println(e.getMessage());
        System.out.println("在目标组件出现异常后执行");
    }
}
 <aop:aspect ref="testThrowing">
        <!--设定通知为异常
            method:切面的方法
            pointcut-ref:指定通知作用在那些切入点上-->
        <aop:after-throwing method="doThrow" pointcut-ref="targetPintcut" throwing="e"/>
    </aop:aspect>

AOP最终通知:无论目标组件是否有无异常都会执行 方法正常执行后执行或在异常通知前执行(只能包含1个参数)

package com.chinasofti.test3_1;

import org.aspectj.lang.JoinPoint;

public class TestAfter {
    public void doAfter(JoinPoint jp){
        System.out.println("无论目标组件时候正常执行,都会执行");
    }
}
<aop:aspect ref="testAfter">
            <!--设定通知为最终
                method:切面的方法
                pointcut-ref:指定通知作用在那些切入点上-->
            <aop:after method="doAfter" pointcut-ref="targetPintcut"/>
        </aop:aspect>

总结

通知执行流程

before:组件参数(JoinPoint)

try{

  Target(目标组件)

  }catch(e){

  after-throwing:组件参数(JoinPoint ,Throwable)

}

after:组件参数(JoinPoint)

if(Target正常结束){//如果抛出异常则不执行,最后执行

  after-returning:组件参数(JoinPoint ,Object)

}

环绕通知

环绕通知:切面程序负责调用目标组件的运行,与Struts中的拦截器功能类似,可以完全替代之前的几个通知

切面程序:在类型为环绕通知的切面程序函数中,参数为org.aspectj.lang.ProceedingJoinPoint是JoinPoint的子类,扩展了JoinPoint类,提供了proceed()函数,该函数调用目标组件,并返回目标组件返回的值

package com.chinasofti.test3_1;

import org.aspectj.lang.ProceedingJoinPoint;

public class TestAround {
    public void doAround(ProceedingJoinPoint pjp){
        System.out.println("前置通知");
        try {
            Object ob =  pjp.proceed();
            System.out.println("目标函数的返回值");
            System.out.println("后置通知");
        } catch (Throwable throwable) {
            System.out.println("异常通知");
        }
        System.out.println("最终通知");
    }
}
<aop:aspect ref="testAround">
    <aop:around method="doAround" pointcut-ref="targetPointCut"/>
</aop:aspect>

切入点表达式:用于声明spring容器那些组件的函数是目标函数

 常用切入点表达式分为:

1.匹配java类中全部函数作为目标函数,使用within关键字

2.按函数匹配:匹配的函数作为目标函数,使用execution关键字

3.按bean的id匹配:匹配的bean中全部函数作为目标组件,使用bean关键字

 1 <!--按类匹配 复合规则的类下所有函数都作为切入点-->
 2 <aop:config>
 3         <!--按类匹配-->
 4         <aop:pointcut id=" targetPintcut" expression="within(com.chinasofti.test3_1)"/>
 5         <!--匹配到包下的类-->
 6         <aop:pointcut id="targetPincut" expression="within(com.chinasofti.*)"/>
 7         <!--匹配到包及子包下的类-->
 8         <aop:pointcut id="targetPincut" expression="within(com..*)"/>
 9     </aop:config>
10 <!--按函数匹配-->
11 <aop:pointcut id="target" expression="execution(表达式)"/>
12 <!--
13 execution(返回类型 类路径.类名.函数名 (参数类型用,分开))
14 任意返回类型
15 execution(* 类路径.类名.函数名(参数类型))
16 任意返回类型下指定包任意类
17 execution(* 类路径.*.函数名(参数类型))
18 任意返回类型下指定包下任意了任意函数
19 execution(* 类路径.*.*(参数类型))
20 任意返回类型下只当包或子包下任意类任意函数任意参数
21 execution(* com..*.*(..))
22 -->
23 </aop:pointcut>
24 <!--按bean组件的id匹配-->
25 <aop:pointcut id="target" expression="bean(target)"/>
26 <!--按bean组件名称(含通配符)匹配-->
27 <aop:pointcut id="target" expression="bean(target*)"/>

        

猜你喜欢

转载自www.cnblogs.com/fionalde/p/9118487.html