idea创建Spring项目实现AOP(XML方式与注解方式)

Spring AOP

一. 概述

1. Aop简介

AOP为Aspect Oriented Programming 即面向切面编程,可以说是对面向对象编程(OOP的一种补充)扩展和延伸,是为了解决OOP中产生的开发问题。

2. OOP和AOP

软件开发一直在寻求一种高效开发、护展、维护的方式。从面向过程的开发实践中,前人针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分,形成了面向对象的开发思想(OOP)
例如我们在操作Controller、Server、Dao的时候,面向对象虽然会很好地解决了业务级别的开发。但是于系统级别的开发我们很难聚焦。比如、对于每一个模块需要进行打日志、代码监控、异常处理。以日志为例,如果以OOP的思想,每个层都抽象出方法去实现日志功能,会产生很强的耦合,为了能够更好地将系统级别的代码抽离出来,去掉与对象的耦合,所以用到了AOP
所以

  1. AOP是对OOP的补充
  2. OOP是将程序分解成各个层次的对象,面向业务中的名词领域,侧重点在与抽象
  3. AOP是将程序运行过程分解成各个切面,从程序运行角度考虑程序的结构,面向业务中的动词领域,侧重点在于解耦

3. AOP主要的特点

源码无关性:在不改变源码的前提下,给程序动态统一添加功能
隔离性:低耦合

二 在idea里创建Spring项目

1. 新建spring项目(熟悉的可以直接跳过)

勾选Spring以及Web Application(其他保持默认状态)

在这里插入图片描述
选择项目名称与项目路径——点击Finish(会自动下载spring需要的jar包)
在这里插入图片描述
新建配置文件(Spring Conifg文件)
在这里插入图片描述

2.到官网下载aspect相关的jar包

Spring中进行aop操作除了导入基本的jar包,还需要导入aop相关jar包
下载地址

  1. 然后将jar包移动至lib下
    在这里插入图片描述
  2. 在添加了jar包后,并不会自动给我们build进去,需要手动build。
    在这里插入图片描述
    选择lib中刚刚导入的jar包。
    在这里插入图片描述

三 简单AOP实现

Spring 方面可以使用下面提到的五种通知工作:

通知描述
前置通知在一个方法执行之前,执行通知。
后置通知在一个方法执行之后,不考虑其结果,执行通知。
返回后通知在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知在建议方法调用之前和之后,执行通知。

1. xml式

  1. spring的xml配置文件application.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="userDao" class="demo.UserDao"></bean>

    <!-- 配置切面类 -->
    <bean id="userAspect" class="demo.Aspect.UserAspectXML"></bean>


    <!-- 配置 AOP -->
    <aop:config>
      <!-- 配置切点表达式 -->
      <!--
         整个表达式可以分为五个部分:
         1、execution()::表达式主体。
         2、第一个*号:表示返回类型, *号表示所有的类型。
         3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service包、子孙包下所有类的方法。
         4、第二个*号:表示类名,*号表示所有的类。
         5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数
      -->
        <!-- 配置切点 -->
        <aop:pointcut expression="execution(* demo.UserDao.saveUser(..))" id="pointcut1" />

        <aop:pointcut expression="execution(* demo.UserDao.deleteUser(..))" id="pointcut2" />

        <aop:pointcut expression="execution(* demo.UserDao.updateUser(..))" id="pointcut3" />

        <aop:pointcut expression="execution(* demo.UserDao.queryUser(..))" id="pointcut4" />
        <!-- 配置切面及通知 -->
        <aop:aspect ref="userAspect">
            <!-- 前置通知 -->
            <aop:before method="before" pointcut-ref="pointcut1" />
            <!-- 后置通知 -->
            <aop:after method="after" pointcut-ref="pointcut2" />
        <!--     环绕通知-->
            <aop:around method="around" pointcut-ref="pointcut3" />

            <!-- 异常抛出通知 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e" />
            <!--  返回通知  -->
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut4" returning="result" />
        </aop:aspect>

    </aop:config>

</beans>
  1. 目标类UserDao代码如下:
package demo;

/**
* @version 1.0
* @author: lixiaoli
* @ClassName: UserDao
* @ProjectName springDemo2
* @date 2019/1/30  15:14
*/
public class UserDao {
   public void saveUser(){
       System.out.println("=======save========");
       System.out.println("save完成");
   }
   public void updateUser(String name){
       System.out.println("=======update========"+name);
       System.out.println("update完成");
   }
   public void deleteUser(){
       System.out.println("=======delete========");
       System.out.println("delete完成");
   }

   public String  queryUser() {
       System.out.println("=======query========");
       System.out.println("query完成");
       return "李小立";
   }
}

  1. 切面类UserAspectXML,可以设置切面中五种不同的通知方法。
 package demo.Aspect;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * @version 1.0
 * @author: lixiaoli
 * @ClassName: UserAspectXML
 * @ProjectName springDemo2
 * @date 2019/1/30  15:15
 */
public class UserAspectXML {
    // 前置通知
    public void before() {
        System.out.println("前置通知===========");
    }

    // 后置通知:
    public void after() {
        System.out.println("后置通知============");
    }

    // 环绕通知:
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知==========");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后通知==========");
        return obj;
    }

    // 异常抛出通知:
    public void afterThrowing(Throwable e) {
        System.out.println("异常抛出通知=========" + e.getMessage());
    }

   //返回通知
    public void afterReturning(Object result) {
        System.out.println("返回通知===========" + result);
    }
}

  1. 最后在新建一个演示类DemoMainXML
public class DemoMainXML {
    public static void main(String[] args) {
        ApplicationContext app=new ClassPathXmlApplicationContext("application.xml");
        UserDao userDao =  (UserDao)app.getBean("userDao");
         //userDao.saveUser();
        //userDao.deleteUser();
        userDao.updateUser("小立");
        //userDao.queryUser();
 }
}

得到结果:
在这里插入图片描述

2. 注解式

  1. SpringAOP中的注解
    @Aspect声明这是一个切面类
    支持 5 种类型的通知注解:
    @Before: 前置通知, 在方法执行之前执行
    @After: 后置通知, 在方法执行之后执行
    @Around: 环绕通知, 围绕着方法执行
    @AfterThrowing: 异常通知, 在方法抛出异常之后
    @AfterRunning: 返回通知, 在方法返回结果之后执行

  2. spring的配置文件-----application2.xml 开启注解的AOP的开发

<?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="userDao" class="demo.UserDao"></bean>

    <!-- 配置切面类 -->
    <bean id="userAspectA" class="demo.Aspect.UserAspectA"></bean>

    <!-- 在配置文件中开启注解的AOP的开发 -->
    <aop:aspectj-autoproxy/>

</beans>
  1. UserDao类同上述xml方式的。
@Aspect
public class UserAspectA {
   // 前置通知:
   @Before(value = "UserAspectA.pointcut1()")
   public void before() {
       System.out.println("前置通知===========");
   }

   // 后置通知:
   @After(value = "UserAspectA.pointcut2()")
   public void after() {
       System.out.println("后置通知============");
   }


   // 环绕通知:
   @Around(value = "UserAspectA.pointcut3()")
   public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
       System.out.println("环绕前通知==========");
       Object obj = joinPoint.proceed();
       System.out.println("环绕后通知==========");
       return obj;
   }

   // 异常抛出通知:
   @AfterThrowing(value = "UserAspectA.pointcut4()", throwing = "e")
   public void afterThrowing(Throwable e) {
       System.out.println("异常抛出通知=========" + e.getMessage());
   }

   //返回通知
   @AfterReturning(value = "UserAspectA.pointcut4()", returning = "result")
   public void afterReturning(Object result) {
       System.out.println("返回通知===========" + result);
   }

   // 切入点注解:
   @Pointcut(value = "execution(* demo.UserDao.saveUser(..))")
   private void pointcut1() {
   }

   @Pointcut(value = "execution(* demo.UserDao.deleteUser(..))")
   private void pointcut2() {
   }

   @Pointcut(value = "execution(* demo.UserDao.updateUser(..))")
   private void pointcut3() {
   }

   @Pointcut(value = "execution(* demo.UserDao.queryUser(..))")
   private void pointcut4() {
   }

}

  1. 新建一个演示类DemoMainA
public class DemoMainA {

   public static void main(String[] args){
       ApplicationContext app=new ClassPathXmlApplicationContext("application2.xml");
       UserDao userDao =  (UserDao)app.getBean("userDao");
       userDao.saveUser();
       //userDao.deleteUser();
       userDao.updateUser("小立");
       userDao.queryUser();
   }
}

得到结果与XML方式AOP完全一致。
在这里插入图片描述
版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_44614710/article/details/86763057

  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值