AOP

作者: kanaSki | 来源:发表于2019-08-12 21:29 被阅读0次

AOP:面向切面编程
正常程序执行顺序都是纵向执行流程。AOP是在原有纵向执行过程之中添加一个横切面,不需要修改原有程序代码(体现出程序高扩展性)。
原有功能相当于释放部分逻辑。

面向切面编程:在程序原有纵向执行流程中,针对某一个或者某一些方法添加通知形成横切面的过程。

常用概念:
原有功能:切点,pointCut
前置通知:在切点之前执行的方法或者功能,before advice
后置通知:在切点之后执行的方法或者功能,after advice
如果切点执行过程中出现异常,将触发异常通知,throws advice
所有功能总称为切面
织入:将切面嵌入到原有功能的过程

Spring提供两种AOP实现方式:
1.Schema-based(每个通知都需要实现接口或类),在spring配置文件内,在<aop:config>配置
实现步骤:
(1)导入jar(spring基础包+aopalliance+aspectweaver+commons-logging+spring-aop+spring-aspect+spring-tx)
(2)新建通知类
(3)配置spring配置文件
引入aop命名空间
配置通知类的<bean>
配置切面
编写测试代码
运行结果
表示通配符,可以匹配任意方法名,任意类名,任意一级包名
如果希望匹配任意方法参数,使用(..),如
com..(..)

appllicationContext.xml:

<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"
       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">
    <bean id="demo" class="com.Demo"/>
    <bean id="mybefore" class="com.advice.MyBeforeAdvice"/>
    <bean id="myafter" class="com.advice.MyAfterAdvice"/>
    <aop:config>
        <aop:pointcut id="mypoint" expression="execution(* com.Demo.demo2())"></aop:pointcut>
        <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
        <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    </aop:config>
</beans>

MyAfterAdvice:

package com.advice;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class MyAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("方法返回值:" + o);
        System.out.println("方法对象:" + method.getName());
        System.out.println("方法参数:" + objects);
        System.out.println("方法所在对象:" + o1);
        System.out.println("执行后置通知");
    }
}

MyBeforeAdvice:

package com.advice;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("方法对象:" + method.getName());
        System.out.println("方法参数:" + objects);
        System.out.println("方法所在对象:" + o);
        System.out.println("执行前置通知");
    }
}

Demo:

package com;

public class Demo {
    public void demo1() {
        System.out.println("demo1");
    }

    public void demo2() {
        System.out.println("demo2");
    }

    public void demo3() {
        System.out.println("demo3");
    }
}

Test:

package com;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Demo demo = ac.getBean("demo", Demo.class);
        demo.demo2();
    }
}

环绕通知:(前置通知与后置通知写在一个方法中)

package com.advice;


import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyArround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println(1);
        Object result = methodInvocation.proceed();
        System.out.println(2);
        return result;
    }
}

    <bean id="demo" class="com.Demo"/>
    <bean id="myArround" class="com.advice.MyArround"></bean>
    <aop:config>
        <aop:pointcut id="mypoint" expression="execution(* com.Demo.demo1())"/>
        <aop:advisor advice-ref="myArround" pointcut-ref="mypoint"/>
    </aop:config>

2.AspectJ(每个通知不需要实现接口),配置spring配置文件时<aop:config>的子标签<aop:aspect>中配置
当切点报异常时才能够触发异常通知
AspectJ方式提供异常通知方法

    <bean id="demo" class="com.Demo"/>
    <bean id="myThrow" class="com.advice.MyExceptionAdvice"></bean>
    <aop:config>
        <aop:aspect ref="myThrow">
            <aop:pointcut id="mypoint" expression="execution(* com.Demo.demo2())"/>
            <aop:after-throwing method="exceptionThrow" pointcut-ref="mypoint" throwing="ex"/>
        </aop:aspect>
    </aop:config>
package com;

public class Demo {
    public void demo1() {
        System.out.println("demo1");
    }

    public void demo2() throws Exception {
        int i = 1 / 0;
        System.out.println("demo2");
    }

    public void demo3() {
        System.out.println("demo3");
    }
}

package com;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Demo demo = ac.getBean("demo", Demo.class);
        try {
            demo.demo2();
        } catch (Exception e) {
        }
    }
}

注:<aop:after>与<aop:after-returning>当切点正常执行时,执行先后顺序根据标签顺序决定,但是当有异常时,after-returning将不执行。
环绕通知遇到异常时只执行前置通知。
且AsprctJ方式的环绕通知方法需要加参数ProceedingJointPoint

相关文章

网友评论

      本文标题:AOP

      本文链接:https://www.haomeiwen.com/subject/anjpjctx.html