Spring AOP

Spring AOP

3.1 Spring AOP简介

3.1.1 AOP

Aspect-Oriented Programming,面向切面编程。是传统的OOP编程的一个重要的补充。OOP编程,只能子类继承父类的纵向重用。

AOP采用的是横向抽取机制。将分散重复的代码抽离出来,在程序编译或者运行的过程,将代码用到需要的执行地方。

3.1.2 AOP术语

Aspect(切面)

JoinPoint(连接点)

Pointcut(切入点)

Advice(通知增强处理)

Target Object(目标对象)

Proxy(代理)

Weaving(织入)

3.2 AspectJ开发

基于XML配置

1.UserDao.java

package com.sty.dao;

public interface UserDao {

    //添加用户
     void add();

    //删除用户
    void delete();
}

2.UserDaoImpl.java

package com.sty.dao;

public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("增加一个用户");
    }

    public void delete() {
        System.out.println("删除一个用户");
    }
}

3.MyAspect.java

package com.sty.dao.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.lang.NonNull;


/*
* 面向切面类
* */
public class MyAspect {
    /*1.前置通知*/
    public void myBefore(@NonNull JoinPoint  joinPoint){
        System.out.println("前置通知:模拟执行权限。。。。。");
        System.out.println("目标类是:"+joinPoint.getTarget());
        System.out.println(","+"被植入增强处理的目标方法是"+joinPoint.getSignature().getName());
    }

    /*2.后置通知*/
    public void myAfterReturning(@NonNull JoinPoint joinPoint){
        System.out.println("后置通知:模拟记录日志");
        System.out.println("被植入增强处理的目标方法是"+joinPoint.getSignature().getName());

    }
    /*3.环绕通知
    * ProceedingJoinPoint 是JoinPoint子接口,表示可执行的目标方法
    * 1. 必须是Object返回值
    * 2. 参数必须是ProceedingJoinPoint类型
    * 3.必须throws Throwable
     *
    *
    * */
    public Object myAround(@NonNull  ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务‘。。。。");
        //执行当前的方法
        Object proceed = proceedingJoinPoint.proceed();

        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务‘。。。。");
        return proceed;

    }
    /*4.异常通知*/
    public void myAfterThrowing( JoinPoint joinPoint, @NonNull  Throwable throwable){
        System.out.println("异常通知:出错了"+ throwable.getMessage());

    }


    /*5.最终通知*/
 public  void myAfter(){
     System.out.println("模拟方法,释放资源");
 }

}

4.ApplicationContext.xml

<?xml version="1.0" encoding="UTF8"?>
         <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
                xmlns:p="http://www.springframework.org/schema/p"
                xmlns:util="http://www.springframework.org/schema/util"
                xmlns="http://www.springframework.org/schema/beans"
                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/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd">
     <!--1.目标类-->
  <bean id="userDao" class="com.sty.dao.UserDaoImpl"/>


   <!--2.切面-->
<bean id="myAspect" class="com.sty.dao.aspect.MyAspect"/>

   <!--3.Aop编程-->
   <aop:config>
      <!--3.1配置切面-->
      <aop:aspect id="aspect" ref="myAspect">
      <!--3.2配置切点-->
       <aop:pointcut id="myPointCut" expression="execution(* com.sty.dao.UserDaoImpl.add(..))"/>
         <!--3.3配置通知-->
        <aop:before method="myBefore" pointcut-ref="myPointCut"/>
         <aop:around method="myAround" pointcut-ref="myPointCut"/>
         <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>
         <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="throwable"/>
         <aop:after method="myAfter" pointcut-ref="myPointCut"/>
      </aop:aspect>
   </aop:config>



</beans>

5.测试

public class MyTest2 {
    /*自定义切面*/
    @Test
    public void TestDiy() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");

           UserDao userDao = (UserDao) context.getBean("userDao");
            userDao.add();
        System.out.println("------------------");
            userDao.delete();

注解配置

1.UserDao

package com.sty.AnnotationDao;
import org.springframework.stereotype.Repository;
public interface UserDao {

    //添加用户
     void add();

    //删除用户
    void delete();
}

2.UserDaoImpl.java

package com.sty.AnnotationDao;

import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("增加一个用户");
    }

    public void delete() {
        System.out.println("删除一个用户");
    }
}

3.myAspect.java

package com.sty.AnnotationDao.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;


/*
* 面向切面类
* */
@Component
@Aspect //定义一个切面
public class MyAspect {

    /*定义一个表达式*/
    @Pointcut("execution(* com.sty.AnnotationDao.*.*(..))")
    public void myPointCut(){}


    /*1.前置通知*/
    @Before("myPointCut()")
    public void myBefore(@NonNull JoinPoint  joinPoint){
        System.out.println("前置通知:模拟执行权限。。。。。");
        System.out.println("目标类是:"+joinPoint.getTarget());
        System.out.println(","+"被植入增强处理的目标方法是"+joinPoint.getSignature().getName());
    }

    /*2.后置通知*/
    @After("myPointCut()")
    public void myAfterReturning(@NonNull JoinPoint joinPoint){
        System.out.println("后置通知:模拟记录日志");
        System.out.println("被植入增强处理的目标方法是"+joinPoint.getSignature().getName());

    }
    /*3.环绕通知
    * ProceedingJoinPoint 是JoinPoint子接口,表示可执行的目标方法
    * 1. 必须是Object返回值
    * 2. 参数必须是ProceedingJoinPoint类型
    * 3.必须throws Throwable
     *
    *
    * */
    @Around("myPointCut()")
    public Object myAround(@NonNull  ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务‘。。。。");
        //执行当前的方法

        Object proceed = proceedingJoinPoint.proceed();

        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务‘。。。。");
        return proceed;

    }
    /*4.异常通知*/
    @AfterThrowing(value = "myPointCut()",throwing = "throwable")
    public void myAfterThrowing( JoinPoint joinPoint, @NonNull  Throwable throwable){
        System.out.println("异常通知:出错了"+ throwable.getMessage());

    }


    /*5.最终通知*/
    @After("myPointCut()")
 public  void myAfter(){
     System.out.println("模拟方法,释放资源");
 }

}

4.application.xml

<?xml version="1.0" encoding="UTF8"?>
         <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
                xmlns:p="http://www.springframework.org/schema/p"
                xmlns:util="http://www.springframework.org/schema/util"
                xmlns="http://www.springframework.org/schema/beans"
                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/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd">






    <!--指定需要扫描的包-->
    <context:component-scan base-package="com.sty"/>

    <!--启动基于注解的声名式Aspect支持-->
    <aop:aspectj-autoproxy/>

</beans>
原文地址:https://www.cnblogs.com/stydejava/p/14067487.html