一,回顾

1.控制反转(IOC)

  以前创建对象,由我们自己决定,现在我们把管理对象的声明周期权力交给spring;

2.依赖注入(DI)

  A对象需要B对象的支持,spring就把B注入给A,那么A就拥有了B;

  底层通过反射技术实现(Class字节码)

3.具体实现

  (1)实体类

  (2)把实体类注册到xml配置文件中

  (3)通过context上下文对象(spring容器)获取进行使用

二,AOP简介

AOP(Aspect Oriented Programming) 面向切面编程(横向);

OOP面向对象编程(纵向编程)

AOP技术利用"横切",解刨开封装的对象内容,将那些影响了多个类的公共行为封装到一个可重用的模块,并将其命名为"Aspect",即切面,切面就是与主业务无关,却为主业务模块提供额外的扩展,便于减少系统代码的重复性,降低模块之间的耦合性,并利于系统的可操作性和维护性;

AOP底层使用代理技术实现,代理内部有反射技术的影子

三AOP基本概念

1.Aspect(切面)

通常是一个类,里面可以定义切入点和通知

2.JoinPoint(连接点)

被拦截的点,因为spring只支持方法类型的连接点,所以在spring中连接点指定就是被拦截的方法,实际上连接点还可以是字段或者构造器

3.advice(通知)

指拦截到的连接点(方法)之后要执行的增强代码,通知分为:前置,后置,异常,最终,环绕通知(before,after,afterThrowing,afterReturing,around)

4.pointcut(切入点)

对连接点(方法)进行拦截的定义,在程序主要体现为输入切入点表达式

5.tarage(目标对象)

代理的目标对象

6.proxy(代理)

AOP框架自动创建的代理对象

四,spring aop基于xml方式实现

1,添加依赖

  1. <!-- spring-context -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>5.1.0.RELEASE</version>
  6. </dependency>
  7.  
  8. <!-- aop依赖的jar包 -->
  9. <!-- aspectjweaver -->
  10. <dependency>
  11. <groupId>org.aspectj</groupId>
  12. <artifactId>aspectjweaver</artifactId>
  13. <version>1.9.2</version>
  14. </dependency>
  15. <!--aspectjrt -->
  16. <dependency>
  17. <groupId>org.aspectj</groupId>
  18. <artifactId>aspectjrt</artifactId>
  19. <version>1.9.2</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.projectlombok</groupId>
  23. <artifactId>lombok</artifactId>
  24. <version>1.18.2</version>
  25. <scope>provided</scope>
  26. </dependency>

2、UserServiceImpl业务类

  1. public class UserServiceImpl {
  2.  
  3. public boolean delete(int id){
  4. System.out.println("UserServiceImpl.delete..."+id);
  5. return true;
  6. }

3、TranAop切面类

此类为切面类,给业务层类中方法添加增强代码

  1. public class TranAop {
  2. //前置通知
  3. public void before(){
  4. System.out.println("TranAop.before...");
  5. }
  6. //返回值后通知
  7. public void afterReturning(){
  8. System.out.println("TranAop.afterReturning...");
  9. }
  10. //异常通知
  11. public void afterThrowing(Exception ex){
  12. System.out.println("TranAop.afterThrowing..."+ex.getMessage());
  13. }
  14. //后置通知(最终)
  15. public void after(){
  16. System.out.println("TranAop.after...");
  17. }
  18. //环绕通知
  19. public Object around(ProceedingJoinPoint pjp) throws Throwable{
  20. System.out.println("TranAop.around.start");
  21. Object[] args = pjp.getArgs();
  22. Object result = null;
  23. //try {
  24. result = pjp.proceed();//执行目标方法
  25. //} catch (Throwable e) {
  26. // System.out.println("发生异常了哦:"+e.getMessage());
  27. //}
  28. System.out.println("TranAop.around.end");
  29. return result;
  30. }
  31. }

4、beans.xml

我们需要再beans.xml中配置aop;需要在xml中添加头部schema文件引用

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/aop
  9. http://www.springframework.org/schema/aop/spring-aop.xsd">
  10.  
  11. <!-- 声明bean -->
  12. <bean id="user1" class="com.yujun.maven.service.UserServiceImpl"></bean>
  13. <bean id="tranAop" class="com.yujun.maven.aop.TranAop"></bean>
  14.  
  15. <!-- spring aop 配置 -->
  16. <aop:config>
  17. <!-- 声明切面类 id:唯一标识 ref:引用bean的id-->
  18. <aop:aspect id="myAspect" ref="tranAop">
  19. <!-- 声明切入点(拦截哪些方法) 拦截service包中所有类中所有方法-->
  20. <aop:pointcut expression="execution(* com.yujun.maven.service.*.*(..))" id="myPointcut"/>
  21. <!-- 实际开发中,下面5中通知,根据实际情况进行合理的选中,不是说像我们现在这样5种都配置 -->
  22. <!-- 前置通知 method:切面类中的方法名-->
  23. <aop:before method="before" pointcut-ref="myPointcut"/>
  24. <!-- 后置通知 -->
  25. <aop:after method="after" pointcut-ref="myPointcut"/>
  26. <!-- 最终通知 -->
  27. <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
  28. <!-- 异常通知 throwing:是切面类中方法的形参名-->
  29. <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="ex"/>
  30. <!-- 环绕通知 -->
  31. <aop:around method="around" pointcut-ref="myPointcut"/>
  32. </aop:aspect>
  33.  
  34. </aop:config>
  35.  
  36. </beans>

5、测试

  1. public class Demo1 {
  2.  
  3. public static void main(String[] args) {
  4. //context上下文
  5. ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  6. UserServiceImpl bean = context.getBean("user1", UserServiceImpl.class);
  7. bean.delete(10);

运行后的控制台输出结果:

TranAop.before...

TranAop.around.start

UserServiceImpl.delete...10

TranAop.around.end

TranAop.afterReturning...

TranAop.after...

可以看到在目标方法UserServiceImpl.delete的前后有额外的输出语句,也就表名之前我们的aop配置生效;

这里没有看到有关于异常通知的输出,原因是我们目标方法delete没有发生异常,所以就不会执行异常通知;

若想看到异常通知被执行,只需要在目标方法中添加一个可以触发异常的语句即可,当前前提是我们的环绕通知中没有对目标方法进行异常处理;

五,springaop基于注解的方式实现

下面我们使用注解方式来实现aop技术,相对来说注解方式比xml配置更简洁,所以现在实际开发中我们都会优先考虑使用注解方式;

1、AserviceImpl业务类

业务类,我们通常会统一放在service包中;

  1. public class AServiceImpl {
  2.  
  3. public int m1(String s){
  4. System.out.println("AServiceImpl.m1..."+s);
  5. return 100;
  6. }
  7.  
  8. }

2、LogAop切面类

  1. //组件:会把当前类当做bean注册到spring容器中,等效于xml中<bean />
  2. @Component
  3. //切面类:等效于xml中的<aop:aspect />
  4. @Aspect
  5. public class LogAop {
  6. //切入点(拦截哪些类中的哪些方法):等效于xml中<aop:pointcut />
  7. @Pointcut("execution(* com.yujun.maven.service.*.*(..))")
  8. private void pointCut(){
  9.  
  10. }
  11. //前置通知:等效于xml中<aop:before />,里面的pointCut()字符串是本类中的切入点方法
  12. @Before("pointCut()")
  13. public void before(){
  14. System.out.println("LogAop.before...");
  15. }
  16. //返回通知:等效于xml中<aop:after-returning />
  17. @AfterReturning(pointcut="pointCut()",returning="result")
  18. public void afterReturning(Object result){
  19. System.out.println("LogAop.afterReturning..."+result);
  20. }
  21. //异常通知:等效于xml中<aop:after-throwing />
  22. @AfterThrowing(pointcut="pointCut()",throwing="ex")
  23. public void afterThrowing(Exception ex){
  24. System.out.println("LogAop.afterThrowing..."+ex.getMessage());
  25. }
  26. //最终通知:等效于xml中<aop:after />
  27. @After("pointCut()")
  28. public void after(){
  29. System.out.println("LogAop.after...");
  30. }
  31. //环绕通知:等效于xml中<aop:around />
  32. @Around("pointCut()")
  33. public Object around(ProceedingJoinPoint pjp) throws Throwable{
  34. System.out.println("LogAop.around.start...");
  35. Object result = pjp.proceed();//执行目标方法
  36. System.out.println("LogAop.around.end..."+result);
  37. return result;
  38. }
  39. }

此类中我们使用很多注解,每个注解的含义都有详细的说明,这里就不多做额外的解释;

主要说一下@Component注解,次注解是spring的基础注解,被此注解标注的类会被当做组件注册到spring容器中,也就相当于之前我们在xml中配置<bean />,也就是说只要在类上标注此注解,我们就不用像之前一样在xml中使用<bean />标签注册实例了;

3、beans-anno.xml

此xml配置文件我们需要添加context的schema文件头引用

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/aop
  10. http://www.springframework.org/schema/aop/spring-aop.xsd
  11. http://www.springframework.org/schema/context
  12. http://www.springframework.org/schema/context/spring-context.xsd">
  13.  
  14. <!-- 开启扫描包:把base-package指定的包中的类中的组件注册到spring容器中-->
  15. <context:component-scan base-package="com.yujun.maven.aop"/>
  16.  
  17. <!-- 为 @AspectJ标注的类提供代理-->
  18. <aop:aspectj-autoproxy/>
  19. </beans>

<context:component-scan />标签配置的作用就是开启扫包功能,它会扫描base-package属性中指定的包中所有类,然后把类上标注有@Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, @Configuration等注解的类注册添加到spring容器中;

<aop:aspectj-autoproxy/>标签则是为使用@AspectJ注解风格的切面类提供代理,若没有此配置,我们的目标方法时没有aop技术支持的

4、@Service注解

  1. //组件:业务逻辑层的组件,等效于<bean />
  2. @Service
  3. public class AServiceImpl {
  4.  
  5. public int m1(String s){
  6. System.out.println("AServiceImpl.m1..."+s);
  7. return 100;
  8. }
  9.  
  10. }

对于AserviceImpl业务类,我们之前是通过在xml中配置<bean />标签来注册实例,那么这里我们还可以选择使用@Service注解,此注解标注的类会被当做一个服务性质组件实例被注册到spring容器中,等效于xml中<bean />标签配置实例;

注意的是我们还需要在bean-anno.xml中新增一个扫包器,因为此业务类在service包中;

  1. <context:component-scan base-package="com.yujun.maven.service"/>

5、测试

  1. public class Demo2 {
  2.  
  3. public static void main(String[] args) {
  4. //context上下文
  5. ApplicationContext context = new ClassPathXmlApplicationContext("beans-anno.xml");
  6. AServiceImpl a1 = context.getBean(AServiceImpl.class);
  7. a1.m1("admin");
  8. }
  9.  
  10. }

运行之后控制台输出

LogAop.around.start...

LogAop.before...

AServiceImpl.m1...admin

LogAop.around.end...100

LogAop.after...

LogAop.afterReturning...100

可以看到我们注解版的aop技术已经成功实现,就是输出的语句顺序和执行xml方法稍微不同,但是最终的功能实现是没有差别的;

六、小结

对于上述的两种方式aop实现,需要自己下来多多测试,然后认真理解其执行流程,这样才能对aop面向切面技术有一个更深的理解和认识;

在aop注解版方式中,我们介绍的@Component和@Service两个注解以及 xml配置中的<context:component-scan />标签扫描器,我们在后面章节也就着重说明;

spring-第二章-AOP的更多相关文章

  1. 复习Spring第二课--AOP原理及其实现方式

    AOP原理: AOP,面向方面的编程,使用AOP,你可以将处理方面(Aspect)的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect.AOP可以防止代码混乱.AOP的应用范围包括:持久 ...

  2. Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...

  3. Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术

    第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...

  4. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  5. Spring学习指南-第二章-Spring框架基础(完)

    第二章 Spring框架基础 面向接口编程的设计方法 ​ 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...

  6. 第05章 AOP细节

    第05章 AOP细节 1.切入点表达式 1.1 作用 通过表达式的方式定位一个或多个具体的连接点. 1.2 语法细节 ①切入点表达式的语法格式 execution([权限修饰符] [返回值类型] [简 ...

  7. Spring官网阅读(十八)Spring中的AOP

    文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...

  8. 《精通Spring4.x企业应用开发实战》第二章

    昨天联系了一下学长,学长说这个项目因为种种原因代码比较混乱,感觉最坏的打算是从头开始写. 大概询问了一下学长和xianhua学姐的建议,又看了看网上的资料,这个项目开发的技术栈基本就是SpringBo ...

  9. Spring框架之AOP源码完全解析

    Spring框架之AOP源码完全解析 Spring可以说是Java企业开发里最重要的技术.Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Orie ...

  10. Spring 3.0 AOP (一)AOP 术语

    关于AOP.之前我已写过一个系列的随笔: <自己实现简单的AOP>,它的关注点在于实现.实现语言是C#,实现方式为 自定义实现 RealProxy 抽象类.重写Invoke方法,以便进行方 ...

随机推荐

  1. iOS学习之自定义弹出UIPickerView或UIDatePicker(动画效果)

    前面iOS学习之UIPickerView控件的简单使用 用到的UIPickerView弹出来是通过 textField.inputView = selectPicker;   textField.in ...

  2. Linux 入门知识一(附上如何解决Ubuntu的root密码问题)

    .centos有拥有七个控制台,其中第一到第六个是字符界面,第七个是图形界面 切换的快捷键是ctrl+shift+fn(n为自然数)   输入tty的话,可以检查当前处于哪个控制台   如何在cent ...

  3. Kafka总结的一张图

  4. Android中Activity的四种启动方式

    谈到Activity的启动方式必须要说的是数据结构中的栈.栈是一种只能从一端进入存储数据的线性表,它以先进后出的原则存储数据,先进入的数据压入栈底,后进入的数据在栈顶.需要读取数据的时候就需要从顶部开 ...

  5. 142. Linked List Cycle II (List; Two-Pointers)

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...

  6. Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson

    Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等 本人fastJson用了两年,也是从去年才开始接触Gson,希望下面的总结会对博友有用,至于Gso ...

  7. 17. Merge Two Binary Trees 融合二叉树

    [抄题]: Given two binary trees and imagine that when you put one of them to cover the other, some node ...

  8. noi2729 Blah数集

    Blah数集 大数学家高斯小时候偶然间发现一种有趣的自然数集合Blah,对于以a为基的集合Ba定义如下: (1) a是集合Ba的基,且a是Ba的第一个元素: (2)如果x在集合Ba中,则2x+1和3x ...

  9. 【原创】cython and python for kenlm

    未经允许不可转载 Kenlm相关知识 Kenlm下载地址 kenlm中文版本训练语言模型 如何使用kenlm训练出来的模型C++版本 关于Kenlm模块的使用及C++源码说明 加载Kenlm模块命令 ...

  10. bootstrap导入JavaScript插件

    Bootstrap的JavaScript插件可以单独导入到页面中,也可以一次性导入到页面中.因为在Bootstrap中的JavaScript插件都是依赖于jQuery库,所以不论是单独导入还一次性导入 ...