Spring AOP(面向切面编程)及AspectJ框架实现AOP(注解)

什么是AOP

(1)面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而是的业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
(3)使用登录的例子说明AOP
登录流程

AOP的作用

提供声明式事务:允许用户自定义切面
以下名词需要了解下:
1.连接点(JointPoint)
类里面哪些方法可以被增强,这些方法称为连接点
2.切入点(PointCut)
实际被真正增强的方法,称为切入点
3.通知(增强)(Advice)
(1)实际增强的逻辑部分被称为通知(增强)
(2)通知的类型有多种:
前置通知:方法前执行
后置通知:方法后执行
环绕通知:方法前后都执行
异常通知:方法内出现异常才执行
最终通知:方法结束之后,无论怎样都执行,类似于finally
通知可以通俗理解为执行,增加代码
4. 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
5.切面(Aspect):横切关注点 被模块化 的特殊对象。即,它是一个类。
6.目标(Target):被增加代码的对象。
7.代理(Proxy):向目标对象应用通知之后创建的对象。

切入点表达式:

execution (public * com.service.impl….(…))
execution(权限修饰符,返回值类型,类全路径,方法名称,参数列表)
1.execution:指示符,execution是最常用的指示符,用于匹配方法执行的连接点。
2.public:访问修饰符,该参数可选。
3.第一个*号:返回值类型,号表示所有的类型,即通配符。
4.包名:需要拦截的包名,后面的两个点表示当前包和当前包的所有子包,即例子中的com.service.impl包和该包的子孙包下所有类。
5.第二个
号:类名,*号表示所有的类。
*(…):方法名,*号表示所有方法,括号里面表示方法的参数,两个点表示任何参数,可有可无。

spring事务的实现

第一步:

<!--配置声明式事务,用的是spring里面的,会通过构造器注入,需要注入一个数据源
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
    <bean id="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="datasource"/>
    </bean>

第二步:

<!--结合Aop实现事务的织入-->
<!--    配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transaction">
<!--        准备给那些方法配置事务-->
<!--        配置事务的传播特性:new propagation 有七种,一般只用一种required,百度了解-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

第三步:

<!--    配置事务切入
aop:pointcut:目标
aop:advisor advice-ref:要注入的方法-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.mybatis.*.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

第四步:测试

    @Override
    public List<Emp> selectAllEmp() {
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.selectAllEmp();
        try {
            Emp emp = new Emp(null, "令狐冲", 20, "男", "123@qq.com");
            List<Emp> list1 = Arrays.asList(emp);
            this.addMoreByList(list1);
            String[] eids={"25","26","27"};
//            int a=1/0;
            this.deleteMoreByArray(eids);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        }
        return list;
    }

其他例子:

public class DiyPointCut {
    public void before(){
        System.out.println("======前置方法执行=========");
    }
    public void after(){
        System.out.println("======后置方法执行=========");
    }
}

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("更新了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}
<?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="userService" class="com.tzm.Demo1.UserServiceImpl"></bean>
    <bean id="log" class="com.tzm.Demo1.log.Log"/>
    <bean id="afterLog" class="com.tzm.Demo1.log.AfterLog"/>
    <!--用原生spring API实现-->
    <aop:config>
        <!--    切入点-->
        <aop:pointcut id="pointcut2" expression="execution(* com.tzm.Demo1.UserServiceImpl.*(..))"/>
        <!--    执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut2"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut2"/>
    </aop:config>
    
    <!--    用自定义类实现-->
    <bean id="diyPointcut" class="com.tzm.Demo1.diy.DiyPointCut"></bean>
    <aop:config>
        <aop:aspect ref="diyPointcut">
            <aop:pointcut id="point" expression="execution(* com.tzm.Demo1.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>
AspectJ框架实现AOP(注解)

@Before:前置增强
@AfterReturning:后置增强
@Around:环绕增强
@AfterThrowing:异常增强
@After:最终增强
@Pointcut:定义切入点

使用步骤

1.pom.xml

<!--导入aspectJ依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.20</version>
</dependency>

2.编写被增强类:UserDao

/**
 * 被代理的对象
 */
public class UserDao {
  public void add() {
    // TODO Auto-generated method stub
    System.out.println("添加客户");
  }
  public void delete() {
    // TODO Auto-generated method stub
    System.out.println("删除客户");
    int i=1/0;
  }
  public String find() {
    // TODO Auto-generated method stub
    System.out.println("查询客户");
    return "fanhuizhi";
  }
  public void update() {
    // TODO Auto-generated method stub
    System.out.println("修改客户");
  }
}
3.使用AspectJ注解形式:

```java
/**
 * NOP 切面类:就是切点与增强结合
 */
@Aspect
public class MyAspect {
  @Before(value = "execution(* com.UserDao.add(..))")//这里写表达式,写哪些类需要添加
  public void before(JoinPoint joinpoint) {
    System.out.println("前置增强..."+joinpoint);
  }

  @AfterReturning(value = "execution(* com.UserDao.find(..))",returning="returnVal")//这里写表达式,写哪些类需要添加
  public void afterReturning(Object returnVal){
    System.out.println("后置增强..."+"方法的返回值"+returnVal);
  }

  @Around(value = "execution(* com.UserDao.delete(..))")//这里写表达式,写哪些类需要添加
  public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
    System.out.println("环绕前增强...");
    Object obj = proceedingJoinPoint.proceed();
    System.out.println("环绕后增强...");
    return obj;
  }

  @AfterThrowing(value = "execution(* com.UserDao.delete(..))",throwing="ex")//这里写表达式,写哪些类需要添加
  public void afterThrowing(Throwable ex) throws Throwable{
    System.out.println("不跑了出异常了..."+ex.getMessage());
  }

  //@After(value = "execution(* com.UserDao.delete(..))")//这里写表达式,写哪些类需要添加
  @After("MyAspect.MyPointCut()")//类名.方法名
  public void after(){
    System.out.println("最终通知");//不管有没有异常都会通知
  }

  //切点的定义,仅是为了定义一个通用的表达式
  @Pointcut(value = "execution(* com.UserDao.delete(..))")
  private void MyPointCut(){
  }
  
}

4.创建applicationContext.xml

<!--引入aop的约束:-->
xmlns:aop="http://www.springframework.org/schema/aop"
<!-- 自动生成代理 底层就是AnnotationAwareAspectJautoProxyCreator -->
<aop:aspectj-autoproxy/>

<bean id="userDao" class="com.UserDao"/>

<bean id="MyAspect" class="com.MyAspect"/>

5.测试运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子酷兒233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值