博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring初步学习——Spring AOP
阅读量:4100 次
发布时间:2019-05-25

本文共 5922 字,大约阅读时间需要 19 分钟。

Spring AOP简介 

     AOP,Aspect Oriented Program,面向切面编程,也是Spring最为重要的功能之一,在数据库事务中切面编程被广泛使用

一、什么是AOP? 

在面向切面编程中,把功能分为核心业务功能和周边功能:

*核心业务:比如登陆,增加数据,删除数据

*周边功能:比如性能统计,日志,事务管理等等

 周边功能在Spring的面向切面编程AOP思想里面,被定义为切面。在面向切面编程AOP的思想里面,核心业务功能和切面功能,分别独立进行开发,然后把切面功能和核心业务功能交织在一起,这叫AOP

二、AOP的目的:

       AOP能够将那些与业务无关,却能为业务模块所共同调用的逻辑和责任(例如:事务处理、日志管理、权限控制)封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于可拓展性和维护性

三、AOP中的概念:

切入点(Pointcut):在哪些类,哪些方法上切入(where)

通知(Advice):在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能)

切面(Aspect):切面=切入点+通知,通俗点就是,在什么时机,在什么地方,做什么增强!

织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(由Spring来完成)

接下来,我们再来实战一下:

1、在Package【service】下新建【ProductService】类

package service;public class ProductService {    public void doSomeService(){        System.out.println("doSomeService");    }}

 2、在xml文件中装配该bean

 3、在Package【aspect】下准备日志切面【LoggerAspect】类

package aspect;import org.aspectj.lang.ProceedingJoinPoint;public class LoggerAspect {        public Object log(ProceedingJoinPoint joinPoint) throws Throwable {        System.out.println("start log:" + joinPoint.getSignature().getName());        Object object = joinPoint.proceed();        System.out.println("end log:" + joinPoint.getSignature().getName());        return object;    }}

4、再在xml文件中声明业务对象和日志切面

 5、运行TestSpring中的测试代码,在输出核心业务代码的同时,在核心业务的运行之前和运行之后都分别输出了日志信息,运行结果如下:

start log:doSomethingServicedoSomethingServiceeng log:doSomethingService

配置Spring AOP的方式

  • 使用注解
  • 使用XML文件

1》使用注解来配置Spring AOP     

用生活中的一个例子来说明就是类似包租婆和中介商之间的关系,包租婆的核心业务就是签合同,收房租,而把带租客看房和谈价格,交钥匙的这样重复的任务交给了中介商,这就是AOP的思想,让关注点代码和业务代码分离

接下来我们再来看一下包租婆和中介商的代码示例:

1、选择连接点

在Package【pojo】下新建一个【Landlord】类,包租婆

package pojo;import org.springframework.stereotype.Component;@Component("landlord")public class Landlord {    public void service() {        // 仅仅只是实现了核心的业务功能        System.out.println("签合同");        System.out.println("收房租");    }}//这个操作其实就是选择连接点,即选择哪一个类的哪一方法用以增强功能//我们这里选择了上述Landlord类中的service()方法作为连接点

2、创建切面,定义切点

我们可以把切面理解为一个拦截器,当程序运行到连接点的时候,被拦截下来,在开头加入了初始化的方法,在结尾也加入了销毁的方法而已,在Spring中只要使用@Aspect注解一个类,那么Spring IOC容器就会认为这是一个切面了

    Spring通过注解中的正则表达式判断具体要拦截的是哪一类的哪一个方法

  • execution:代表执行方法的时候会触发
  • * :代表任意返回类型的方法
  • pojo.Landlord:代表类的全限定名
  • service():被拦截的方法名称

execution(* pojo.Landlord.service()),通过这个表达式Spring就知道应该拦截pojo.Landlord类下的service方法,使用@Pointcut可以更加简洁

在Package【aspect】下新建一个中介商【Broker】

package aspect;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Component@Aspect//注意:被定义为切面的类任然是一个Bean,需要@Component注解标注class Broker {    @Before("execution(* pojo.Landlord.service())")    public void before(){        System.out.println("带租客看房");        System.out.println("谈价格");    }    @After("execution(* pojo.Landlord.service())")    public void after(){        System.out.println("交钥匙");    }}

或者也可以这么写(使用@Pointcut注解):

package aspect;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component@Aspectclass Broker {    @Pointcut("execution(* pojo.Landlord.service())")    public void lService() {    }    @Before("lService()")    public void before() {        System.out.println("带租客看房");        System.out.println("谈价格");    }    @After("lService()")    public void after() {        System.out.println("交钥匙");    }}

3、在applicationContext.xml中配置自动注入,并告诉Spring IOC容器去哪里扫描这两个Bean

4、在Package【test】编写测试代码:

package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import pojo.Landlord;public class TestSpring {    public static void main(String[] args) {        ApplicationContext context =                new ClassPathXmlApplicationContext("applicationContext.xml");        Landlord landlord = (Landlord) context.getBean("landlord", Landlord.class);        landlord.service();    }}

接下来我们来了解一下Spring AspectJ注解:

@Before 前置通知,在连接点方法前调用
@After 后置通知,在连接点方法后调用
@Around 环绕通知,它将覆盖原有方法,但是允许你通过反射调用原有方法
@AfterReturning 返回通知,在连接点方法执行并正常返回后调用,要求连接点方法在执行过程中没有发生异常
@AfterThrowing 异常通知,当连接点方法异常时调用

【环绕通知】

package aspect;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Component@Aspectclass Broker {//  注释掉之前的 @Before 和 @After 注解以及对应的方法//  @Before("execution(* pojo.Landlord.service())")//  public void before() {//      System.out.println("带租客看房");//      System.out.println("谈价格");//  }////  @After("execution(* pojo.Landlord.service())")//  public void after() {//      System.out.println("交钥匙");//  }    //  使用 @Around 注解来同时完成前置和后置通知    @Around("execution(* pojo.Landlord.service())")    public void around(ProceedingJoinPoint joinPoint) {        System.out.println("带租客看房");        System.out.println("谈价格");        try {            joinPoint.proceed();        } catch (Throwable throwable) {            throwable.printStackTrace();        }        System.out.println("交钥匙");    }}

2》使用XML配置开发Spring AOP

AOP中可以配置的元素:

AOP配置元素 用途 备注
aop:advisor 定义AOP的通知 一种古老的方式很少使用
aop:aspect 定义一个切面 ——
aop:before 定义前置通知 ——
aop:after 定义后置通知 ——
aop:around 定义环绕通知 ——
aop:afterreturning 定义返回通知 ——
aop:afterthrowing 定义异常通知 ——
aop:config 顶层的AOP配置元素 AOP的配置是以它为开始
aop:declareparents 给通知引入新的额外接口,增强功能 ——
aop:pointcut 定义切点 ——

我们去掉之前的注释,用XML配置

我是通过学习一位博主(@我没有三颗心脏)的博客,讲的很详细,大家也可以参考原网址:

2018/11/18

今天第一次开始ssm框架的整合,整合过程中。没错,是不可能的,首先applicationContext.xml中<beans>标签中的xmlns内容写错了,下次记得要细心些,还有spring-mybatis.xml,另外jdbc.properties编写时需要注意,最重要的配置修改完成之后,输出没有问题,可是不知道为什么数据库中有内容,可是用框架查询结果就为null让我很是费解,最后发现问题是在我的数据库表的列字段和实体类的属性名称不一致导致的查询结果为null,下次记得要统一哦!

转载地址:http://tgeii.baihongyu.com/

你可能感兴趣的文章
centos7 下修改MySQL密码
查看>>
Linux中vim设置
查看>>
MySQL权限管理
查看>>
killall出现-bash: killall: command not found及使用方法
查看>>
python2与python3的decode()与encode()函数
查看>>
python常用模块os
查看>>
SourceTree error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
查看>>
Authentication failed for
查看>>
2020考研回顾总结
查看>>
python基础(一)之分形树(递归的用法)
查看>>
《算法笔记》例题解析 第2章C++快速入门--2顺序结构(6题)2021-02-10
查看>>
《算法笔记》例题解析 第2章C++快速入门--3选择结构(5题)2021-02-18
查看>>
《算法笔记》例题解析 第2章C++快速入门--4循环结构(9题)2021-02-23
查看>>
《算法笔记》例题解析 第2章C++快速入门--5数组(9题)2021-02-24
查看>>
《算法笔记》例题解析 第2章C++快速入门--6函数(2题)2021-02-28
查看>>
《算法笔记》例题解析 第2章C++快速入门--10黑盒测试(8题)2021-03-02
查看>>
2.1算法之入门经典--简单模拟(完结)
查看>>
《算法笔记》例题解析 第3章入门模拟--6字符串处理(9题)2021-03-04
查看>>
算法之数学--同模余定理,最大公约数(GCD),最小公倍数(LCM)2021-03-07
查看>>
算法之数学--斐波那契数列,素数判定,素数筛选2021-03-08
查看>>