xml开发中的各种通知

AOP的术语

   Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只 支持方法类型的连接点. 
   Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义. 
   Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置通知,
                 后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能) 
   Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类 动态地添加一些方法或 Field. 
   Target(目标对象):代理的目标对象 
   Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.  spring 采用动态代理织入,
               而 AspectJ 采用编译期织入和类装在期织入 
   Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类 
   Aspect(切面): 是切入点和通知(引介)的结合 

依赖包的引入

这个也很坑,,
点击这里

Spring整合Junit进行测试

在测试类上加上这两句注解就可以对测试类里的对象进行依赖注入
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:/aop编程/aopTest.xml”)

package aop编程;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

/**
 * Created by Administrator on 2018/10/7.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/aop编程/aopTest.xml")
/*
有以上的注解,我们就可以直接在类上进行对象注入
Spring整合Junit
 */
public class testDemo {

    @Resource(name="deleUser")
    private userDao user;

    @Test
    public void testDemo1(){
        user.add("小明");
        user.deleUser("小明");
        user.update("小明");
        user.save();
    }


}

切面类

首先的有一个切面类,才能对目标方法进行增强
在xml中
语法:<aop:aspect ref=“被增强的目标类”>配置通知 </aop:aspect>
切面类

package aop编程;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.omg.CORBA.Object;

/**
 * Created by Administrator on 2018/10/7.
 * 切面类
 */
public class aspect {
    public void before1(JoinPoint joinPoint){
        System.out.println("dele执行前的检测..."+joinPoint);
    }

    //参数名必须叫result,和xml里的after-retuing的result一样
    public void after1(String result){
        //这里加不了参数,,,也不知道为什么
        System.out.println("执行add方法后..."+result);
    }

    public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
        System.out.println("调用update方法前");
        Object obj= (Object) joinpoint.proceed();
        System.out.println("调用update方法之后");
        return obj;
    }

    public void afterThrow(Throwable ex){
        System.out.println("异常被抛出...."+ex.getMessage());
    }

    public void finals(){
        System.out.println("异常最终被通知");
    }
}

先说一下我的xml文件

aopTest.xml

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans.xsd
                     http://www.springframework.org/schema/aop
                     http://www.springframework.org/schema/aop/spring-aop.xsd
                     http://www.springframework.org/schema/context
                     http://www.springframework.org/schema/context/spring-context.xsd">
    <!--需要映入aop的约束-->
    <!--不扫描,切面类里面加了参数的方法就增强不了-->
    <context:component-scan base-package="aop编程"/>
    
    <bean id="deleUser" class="aop编程.userDao"></bean>
    <bean id="userDao" class="aop编程.aspect"></bean>
<!--aop的配置-->
    <aop:config>
        <!--aop切入点表达式的配置,说明那些方法需要增强-->
        <aop:pointcut expression="execution(* aop编程.userDao.deleUser(..))" id="pointcut1"/>
        <aop:pointcut expression="execution(* aop编程.userDao.add(..))" id="pointcut2"/>
        <aop:pointcut expression="execution(* aop编程.userDao.update(..))" id="pointcut3"/>
        <aop:pointcut expression="execution(* aop编程.userDao.save(..))" id="pointcut4"/>
        <!--配置切面-->
            <aop:aspect ref="userDao">
                <!--前置通知-->
                <aop:before method="before1" pointcut-ref="pointcut1" />
                <!--后置通知-->
                <aop:after-returning method="after1" pointcut-ref="pointcut2" returning="result"/>
                <!--环绕通知-->
                <aop:around method="around" pointcut-ref="pointcut3" />
                <!--retuing里的名字可以随便取,但是必须和after的参数名相同也叫result-->
                
                <!--异常通知-->
                <aop:after-throwing method="afterThrow" pointcut-ref="pointcut4" throwing="ex" />

                <!--最终通知-->
                <aop:after method="finals" pointcut-ref="pointcut4" />
            </aop:aspect>
    </aop:config>
</beans>

被增强的类userDao

package aop编程;

/**
 * Created by Administrator on 2018/10/7.
 */
public class userDao {
    public boolean deleUser(String name){
        System.out.println(name+"被成功删除deleUser");
        return true;
    }

    public void update(String name){
        System.out.println(name+"被更新update");
    }

    public void save(){
        System.out.println("调用userDao.save().....");
        int num=1/0;
    }

    public String add(String name){
        System.out.println(name+"被添加进来add");
        return "aaaaa";
    }
}


切点

即被增强的类中的方法,一般只需要在xml文件里的切面配置即可,之后调用
方法会自动被增强
<aop:pointcut expression=“execution(方法路径)” id=“切点名称”/>
这里说一下expression语法
方法前面的 * 是匹配所有返回类型
class.* 包含class类下的所有方法
*. *. *.method() 包含所有包下的子包的子包的method方法
class+.method() 包含class及其子类下的method方法
class.*od() 包含class下的以od结尾方法

前置通知

对所增强的方法,在执行之前进行的方法
xml中

            <aop:before method="增强的方法" pointcut-ref="切点名" />

后置通知

对所增强的方法,在执行之前进行的方法
<aop:after-returning method=“增强的方法” pointcut-ref=“切点名” returning=“result”/>
这里的returning的名字必须和切面类的后置方法相同,相当与传给后置方法
以上面例子为例

//参数名必须叫result,和xml里的after-retuing的result一样
    public void after1(String result){
        //这里加不了参数,,,也不知道为什么
        System.out.println("执行add方法后..."+result);
    }

环绕通知方法

对所增强的方法,在执行之前及之后进行的方法
<aop:around method=“增强的方法” pointcut-ref=“切点名” />
相应的增强方法:

public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
        System.out.println("调用update方法前");
        Object obj= (Object) joinpoint.proceed();//被增强的方法
        System.out.println("调用update方法之后");
        return obj;
    }

异常通知

对所增强的方法,发生异常进行的方法

<aop:after-throwing method="增强的方法" pointcut-ref="切点名" throwing="ex" />

同样,throwing里的名字必须和切面类里的方法匹配

 public void afterThrow(Throwable ex){
        System.out.println("异常被抛出...."+ex.getMessage());
    }

最终通知

这个无论程序怎样都会执行,相当于finally

    <aop:after method="增强的方法" pointcut-ref="切点名" />

让我们看下运行结果把
对了,还有一点要注意一下,就是必须加上扫描,不然切面类里的方法
加了参数后,起不了增强作用

xml开发中的各种通知

可以看见,程序发生了除零异常,程序正确运行