AOP通知类型

来源:互联网 发布:海文网络计划软件教程 编辑:程序博客网 时间:2024/06/01 19:03

分类

  1. 前置通知

    • 在目标类的方法执行之前执行。
    • 配置文件信息:
    • 应用:可以对方法的参数来做校验
  2. 最终通知

    • 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
    • 在配置文件中编写具体的配置:
    • 应用:例如像释放资源
  3. 后置通知

    • 方法正常执行后的通知。
    • 在配置文件中编写具体的配置:
    • 应用:可以修改方法的返回值
  4. 异常抛出通知

    • 在抛出异常后通知
    • 在配置文件中编写具体的配置:
    • 应用:包装异常的信息
  5. 环绕通知

    • 方法的执行前后执行。
    • 在配置文件中编写具体的配置:
    • 要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。

注意:AOP依赖与IoC,在spring里不是使用注解就是配置xml,所以,下面会用到配置文件进行配置通知

步骤

使用maven导包spring-context,会自动引入spring-aop

<dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-context</artifactId>    <version>4.1.6.RELEASE</version></dependency>

提供代理对象PhoneImpl.java

public class PhoneImpl {    public void product5S() {        System.out.println("生产iPhone 5S中");    }    //为下面的异常通知使用    public void testException() {        //设置异常        int i=0/10;        System.out.println("这是异常下面的代码");    }}

提供一个applicationContext.xml,提供一个Test.java测试类

<?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:mvc="http://www.springframework.org/schema/mvc"    xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="http://www.springframework.org/schema/beans            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd            http://www.springframework.org/schema/context             http://www.springframework.org/schema/context/spring-context-3.0.xsd            http://www.springframework.org/schema/aop             http://www.springframework.org/schema/aop/spring-aop-3.0.xsd            http://www.springframework.org/schema/tx             http://www.springframework.org/schema/tx/spring-tx-3.0.xsd            http://www.springframework.org/schema/mvc             http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd            http://www.springframework.org/schema/context             http://www.springframework.org/schema/context/spring-context-3.0.xsd"></beans>

前置通知

提供代理对象BeforeProxy.java

import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class BeforeProxy implements MethodBeforeAdvice{    @Override    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {        System.out.println("前置通知");    }}

配置文件applicationContext.xml中配置前置通知

    <!-- 创建要代理的对象  一下的id随便起名字-->    <bean id="phone" class="com.phone.PhoneImpl"></bean>    <!-- 创建增强对象,也就是通知对象 -->    <bean id="before" class="com.proxy.BeforeProxy"></bean>    <!-- 处理要代理的对象与增强对象之间的关系 -->    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">        <!-- 设置要代理的对象,也就是目标对象 -->        <property name="target" ref="phone"></property>        <!-- 设置拦截器,也就是增强对象 注意使用的是value属性-->        <property name="interceptorNames" value="before"></property>        <!-- 如果为true表示jdk代理,要有接口,如果为false表示可以没有接口 -->        <property name="optimize" value="false"></property>    </bean>

测试

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        PhoneImpl phone=(PhoneImpl)applicationContext.getBean("proxy");        phone.product5S();

运行结果

前置通知生产iPhone 5S中

后置通知

提供后置通知对象AfterProxy.java,注意实现的接口

import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class AfterProxy implements AfterReturningAdvice{    @Override    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {        System.out.println("后置通知");    }}

配置文件applicationContext.xml中增加bean

    <!-- 创建要代理的对象  一下的id随便起名字-->    <bean id="phone" class="com.henu.phone.PhoneImpl"></bean>    <!-- 创建增强对象,也就是通知对象 -->    <bean id="before" class="com.henu.proxy.BeforeProxy"></bean>    <!--增加的地方-->    <bean id="after" class="com.henu.proxy.AfterProxy"></bean>    <!-- 处理要代理的对象与增强对象之间的关系 -->    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">        <!-- 设置要代理的对象,也就是目标对象 -->        <property name="target" ref="phone"></property>        <!-- 设置拦截器,也就是增强对象 注意使用的是value属性-->        <!--修改的地方,同时提供前置和后置通知,这个地方为什么不用ref引用呢,如果用ref会报错,这里可以引入多个对象,如果用ref只能引入一个对象-->        <property name="interceptorNames" value="after,before"></property>        <!-- 如果为true表示jdk代理,要有接口,如果为false表示可以没有接口 -->        <property name="optimize" value="false"></property>    </bean>

运行结果

前置通知生产iPhone 5S中后置通知

环绕通知

提供RoundProxy.java

import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class RoundProxy implements MethodInterceptor{    //可以替代目标方法    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        System.out.println("环绕通知");        //如果没有下面这些,执行的时候目标方法会被替代,只显示上面的一句话        invocation.proceed();//执行原来的方法        return null;    }}

修改配置文件

    <!-- 创建要代理的对象  一下的id随便起名字-->    <bean id="phone" class="com.henu.phone.PhoneImpl"></bean>    <!-- 创建增强对象,也就是通知对象 -->    <bean id="before" class="com.henu.proxy.BeforeProxy"></bean>    <bean id="after" class="com.henu.proxy.AfterProxy"></bean>    <bean id="round" class="com.henu.proxy.RoundProxy"></bean>    <!-- 处理要代理的对象与增强对象之间的关系 -->    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">        <!-- 设置要代理的对象,也就是目标对象 -->        <property name="target" ref="phone"></property>        <!-- 设置拦截器,也就是增强对象 注意使用的是value属性-->        <property name="interceptorNames" value="after,before,round"></property>        <!-- 如果为true表示jdk代理,要有接口,如果为false表示可以没有接口 -->        <property name="optimize" value="false"></property>    </bean>

运行结果

前置通知环绕通知生产iPhone 5S中后置通知

异常通知

提供异常通知代理类ExceptionProxy.java

import java.lang.reflect.Method;import org.springframework.aop.ThrowsAdvice;//该接口没有任何方法需要实现,需要自己写public class ExceptionProxy implements ThrowsAdvice{    /*public void afterThrowing(Throwable throwable) {    }*/     public void afterThrowing(Method m,Object[] os,Object obj,Throwable throwable) {        System.out.println("异常通知");    }}

修改配置文件

    <!-- 创建要代理的对象  一下的id随便起名字-->    <bean id="phone" class="com.henu.phone.PhoneImpl"></bean>    <!-- 创建增强对象,也就是通知对象 -->    <bean id="before" class="com.henu.proxy.BeforeProxy"></bean>    <bean id="after" class="com.henu.proxy.AfterProxy"></bean>    <bean id="round" class="com.henu.proxy.RoundProxy"></bean>    <bean id="throwss" class="com.henu.proxy.ExceptionProxy"></bean>    <!-- 处理要代理的对象与增强对象之间的关系 -->    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">        <!-- 设置要代理的对象,也就是目标对象 -->        <property name="target" ref="phone"></property>        <!-- 设置拦截器,也就是增强对象 注意使用的是value属性-->        <property name="interceptorNames" value="after,before,round,throwss"></property>        <!-- 如果为true表示jdk代理,要有接口,如果为false表示可以没有接口 -->        <property name="optimize" value="false"></property>    </bean>

修改测试类Test.java

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        PhoneImpl phone=(PhoneImpl)applicationContext.getBean("proxy");        //要修改的地方        phone.testException();

测试结果,打印出了 异常通知

前置通知环绕通知异常通知Exception in thread "main" java.lang.ArithmeticException: / by zero    at com.henu.phone.PhoneImpl.testException(PhoneImpl.java:10)    at com.henu.phone.PhoneImpl$$FastClassBySpringCGLIB$$edc957f1.invoke(<generated>)    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)    at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:125)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)    at com.henu.proxy.RoundProxy.invoke(RoundProxy.java:12)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)    at com.henu.phone.PhoneImpl$$EnhancerBySpringCGLIB$$d04c134a.testException(<generated>)    at com.henu.proxy.Test.main(Test.java:12)

最终通知

无论目标方法是否遇到异常都会执行,相当于代码中的finnaly

。。。这个以后补充。。。

原创粉丝点击