Spring学习_AOP_通知

AOP

为什么要使用AOP?
有三个类,每个类里都有一个add Student()方法,如果我们每次执行addStudent()前都需要检查数据库内是否已经存在我们要增加的学生,就需要分别在三个方法前添加check()方法,很麻烦,不是吗?
so…
有了AOP(当然远不止这点功能呢),可以指定那谁谁,虚拟机你在每次跑addStudent()前都来给我调用check()来检查下,哈哈,苦逼的虚拟机。
简单的前置通知
1、xml配置

<!--    配置前置通知-->
<!--    addPerson所在方法-->
    <bean id="personServiceImpl" class="com.itheima.service.PersonServiceImpl">
        <property name="personDao" ref="personDao">

        </property>
    </bean>
<!--    前置通知类-->
    <bean id="logBefore" class="com.itheima.aop.LogBefore">

    </bean>
<!--    关联-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public void com.itheima.service.PersonServiceImpl.deletePerson(int)) or execution(public void com.itheima.service.PersonServiceImpl.addPerson(com.itheima.entity.Person))"/>
        <aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
    </aop:config>

expresstion表达式举例说明:
1、任意公共方法的执行:
execution(public * (…))
2、任何一个以“set”开始的方法的执行:
execution(
set*(…))
3、AccountService
接口的任意方法的执行:
execution(* com.xyz.service.AccountService.(…))
4、定义在service包里的任意方法的执行:
execution(
com.xyz.service..(…))
5、定义在service包和所有子包里的任意类的任意方法的执行:
execution(* com.xyz.service….(…))
6、定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:
execution(* com.test.spring.aop.pointcutexp…JoinPointObjP2.(…))")
最靠近(…)的为方法名,靠近.
(…))的为类名或者接口名

2、前置通知类
LogBefore.java实现MethodBeforeAdvice接口

public class LogBefore implements MethodBeforeAdvice {
    
    
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
    
    
        System.out.println("前置通知!");
    }
}

后置通知就不写了,大同小异,赶时间。
异常通知
在容器中配置异常通知

   <bean id="logException" class="com.itheima.aop.LogException"/>
<!--    异常通知-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public void com.itheima.service.PersonServiceImpl.deletePerson(int)) or execution(public void com.itheima.service.PersonServiceImpl.addPerson(com.itheima.entity.Person))"/>
        <aop:advisor advice-ref="logException" pointcut-ref="pointcut"/>
    </aop:config>

异常通知类,注意,我们在实现接口的时候并没有提示我们要实现哪个方法,但是我们仍要实现以下方法:

package com.itheima.aop;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class LogException implements ThrowsAdvice {
    
    
    public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable){
    
    
        System.out.println("异常通知:目标对象," + target + "方法名," + method.getName() + "方法的参数个数:" + args.length + "异常类型:" + throwable.getMessage());
    }
}

故意在添加人类中让personDao空指针后,执行:
在这里插入图片描述
环绕通知:是一个功能最强大的通知,可以在任何地方通知,可以获得目标方法的全部控制权。
新建环绕类:LogArround .java

package com.itheima.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class LogArround implements MethodInterceptor {
    
    
    @Override
    public Object invoke(MethodInvocation invocation){
    
    
        Object result = null;
        try {
    
    
            //  前置通知
            System.out.println("环绕前置");
            result = invocation.proceed();//控制目标方法的执行,前面是前置通知,后面是后置通知
            //后置通知
            System.out.print("环绕后置通知:");
            System.out.println("目标对象," + invocation.getThis() + "方法名," + invocation.getMethod().getName() + "方法的参数个数:" + invocation.getArguments().length + "返回参数:" + result);
        } catch (Throwable throwable) {
    
    
            //环绕异常通知
            System.out.println("环绕异常通知");
        }
        return result;
    }
}

在这里插入图片描述

愿你心如花木,向阳而生

猜你喜欢

转载自blog.csdn.net/nbcsdn/article/details/99424449