Spring框架(二)————AOP使用扩展

一.AOP
1.简介;AOP(Aspect Oriented Programming 面向切面编程),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,提高程序的可重用性,同时提高了开发的效率
AOP可以说也是这种目标的一种实现。AOP是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果

常用于日志记录,性能统计,安全控制,事务处理,异常处理等等。

2.作用:将重复性的代码抽取出来,放在专门的类和方法中,便于管理和维护

3.面向切面编程AOP的基本概念:
(1)切面(Aspect): 一个模块化的横切逻辑,可能会横切多个对象。
(2)连接点(Join Point): 程序执行中的某个具体执行点。
(3)增强处理(Advice): 切面在某个特定连接点上执行的代码逻辑
(4)切入点(Pointcut): 对连接点的特征进行描述,可以使用正则表达式。增强处理和一个切入点表达式相关联,并在与这个切入点匹配的某个连接点上运行。
(5)目标对象(Target object):被一个或多个切面增强的对象。
(6)AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能。
(7)织入(Weaving):将增强处理连接到应用程序中的类型或对象上的过程。
(8)增强处理类型:前置增强,后置增强,环绕增强,异常抛出异常,最终增强等。
前置通知(Before):在目标方法被调用之前调用通知功能。
后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。
返回通知(After-returning):在目标方法成功执行之后调用通知。
异常通知(After-throwing):在目标方法抛出异常后调用通知。
环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

4.AOP的实例

关于前置增强,后置增强,后置增强带返回值,后置增强带异常的代码如下:
(1).实体类Target

public class Target {

    public String show(String name) throws Exception {
        System.out.println("这是目标方法...");
        if (1/0==1){
            throw new Exception("除数不能为0");
        }
        return "hello"+name;
    }
}

(2).增强类AdviceTarget

import org.aspectj.lang.JoinPoint;
import java.util.logging.Logger;

public class AdviceTarget {
    private static final Logger log=Logger.getLogger(String.valueOf(AdviceTarget.class));
    //前置增强
    public void before(JoinPoint point){
        System.out.println("目标对象:"+point.getTarget()+"方法名:"+point.getSignature().getName()+
                "方法入参"+ point.getArgs());
        }
    //后置增强
    public void after(JoinPoint point){
        System.out.println("后置增强");
    }
    //后置增强带返回值
    public void afterReturn(JoinPoint point,Object value){
        System.out.println("后置带返回值:"+value);
    }
    //后置增强带异常
    public void afterException(JoinPoint point,Exception ex){
        System.out.println("后置带异常:"+ex);
    }
 }

(3).创建spring配置文件:spring_aop.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"
       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="target" class="com.bdqn.aop.Target"/>
    <bean id="adviceTarget" class="com.bdqn.aop.AdviceTarget"/>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public String show(String))"/>
        <aop:aspect ref="adviceTarget">
            <!--前置增强-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <!--后置增强-->
            <aop:after method="after" pointcut-ref="pointcut"/>
            <!--后置增强带返回值-->
            <aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="value"/>
            <!--后置增强带异常-->
            <aop:after-throwing method="afterException" pointcut-ref="pointcut" throwing="ex"/>
        </aop:aspect>
    </aop:config>

</beans>

(4).编写测试类

import com.bdqn.aop.Target;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Junit {
   
    @Test
    public void testAop(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring_aop.xml");
        Target target=(Target)context.getBean("target");

        try {
            target.show("张三");
        } catch (Exception e) {
            System.out.println("除数不能为0");
        }
    }
}

执行结果如下图:
Spring框架(二)————AOP使用扩展

关于环绕增强的代码
(1).实体类Target

public class Target {

    public String show(String name) throws Exception {
        System.out.println("这是目标方法...");
        return "hello"+name;
    }
}

(2).增强类AdviceTarget

 //环绕增强
    public void around(ProceedingJoinPoint point){
        String str=(String)point.getArgs()[0];
        if (str.equals("admin")){
            //有权限,可以访问目标方法
            try {
                String value=point.proceed().toString();
                System.out.println("返回值"+value);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }else {
            System.out.println("无权限访问");
        }
    }

(3).创建spring配置文件:spring_aop.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">

    <bean id="target" class="com.bdqn.aop.Target"/>
    <bean id="adviceTarget" class="com.bdqn.aop.AdviceTarget"/>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public String show(String))"/>
        <aop:aspect ref="adviceTarget">
         
            <!--环绕增强-->
            <aop:around method="around" pointcut-ref="pointcut" />
        </aop:aspect>
    </aop:config>
    
</beans>

(4).测试类

 @Test
    public void testAop(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring_aop.xml");
        Target target=(Target)context.getBean("target");
        try {
            target.show("admin");
        } catch (Exception e) {
            System.out.println("除数不能为0");
        }
    }

执行结果:返回值admin