解析Spring第三天(面向切面AOP)

面向切面:AOP

在不修改源代码的基础上,对方法进行增强。AOP的底层原理就是代理技术(第一种:jdk的动态代理(编写程序必须要有接口)。第二种:cglib代理技术(生成类的子类)。如果编写的程序有借口,则spring框架会自动使用jdk的动态代理技术增强,)。

Joinpoint(连接点) 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点

Pointcut(切入点) -- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义

Advice(通知/增强)-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Target(目标对象)-- 代理的目标对象

Weaving(织入)-- 是指把增强应用到目标对象来创建新的代理对象的过程

Proxy(代理)-- 一个类被AOP织入增强后,就产生一个结果代理类

Aspect(切面)-- 是切入点和通知的结合,以后自己来编写和配置的

创建一个普通的Maven项目工程引入坐标

 1 <dependencies>
 2     <dependency>
 3         <groupId>org.springframework</groupId>
 4         <artifactId>spring-context</artifactId>
 5         <version>5.0.2.RELEASE</version>
 6     </dependency>
 7     <dependency>
 8         <groupId>commons-logging</groupId>
 9         <artifactId>commons-logging</artifactId>
10         <version>1.2</version>
11     </dependency>
12     <dependency>
13         <groupId>log4j</groupId>
14         <artifactId>log4j</artifactId>
15         <version>1.2.12</version>
16     </dependency>
17     <dependency>
18         <groupId>org.springframework</groupId>
19         <artifactId>spring-test</artifactId>
20         <version>5.0.2.RELEASE</version>
21     </dependency>
22     <dependency>
23         <groupId>junit</groupId>
24         <artifactId>junit</artifactId>
25         <version>4.12</version>
26     </dependency>
27
28         <!-- AOP联盟 -->
29         <dependency>
30             <groupId>aopalliance</groupId>
31             <artifactId>aopalliance</artifactId>
32             <version>1.0</version>
33         </dependency>
34         <!-- Spring Aspects -->
35         <dependency>
36             <groupId>org.springframework</groupId>
37             <artifactId>spring-aspects</artifactId>
38             <version>5.0.2.RELEASE</version>
39         </dependency>
40         <!-- aspectj -->
41         <dependency>
42             <groupId>org.aspectj</groupId>
43             <artifactId>aspectjweaver</artifactId>
44             <version>1.8.3</version>
45         </dependency>
46   </dependencies>
  • 创建Spring的配置文件,引入具体的AOP的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:context="http://www.springframework.org/schema/context"
     5        xmlns:aop="http://www.springframework.org/schema/aop"
     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/context
    10                 http://www.springframework.org/schema/context/spring-context.xsd
    11                 http://www.springframework.org/schema/aop
    12                 http://www.springframework.org/schema/aop/spring-aop.xsd">
    13
    14 </beans>
  • 创建包结构,编写具体的接口和实现类

    1 package cn.tx.demo2;
    2 public class UserServiceImpl implements UserService {
    3 ?
    4     @Override
    5     public void save() {
    6         System.out.println("业务层:保存用户...");
    7     }
    8 ?
    9 }
  • 将目标类配置到Spring中

    <bean id="userService" class="cn.tx.demo2.UserServiceImpl"/>
  • 自定义切面类

     1 package cn.tx.demo2;
     2 ?
     3 /**
     4  * 自定义切面类 = 切入点(表达式) + 通知(增强的代码)
     5  */
     6 public class MyXmlAspect {
     7 ?
     8     /**
     9      * 通知
    10      */
    11     public void log(){
    12         // 发送手机短信
    13         // 发送邮件/记录日志/事务管理
    14 ?
    15         System.out.println("增强的方法执行了...");
    16     }
    17 ?
    18 }
  • 在配置文件中定义切面类
    1 <bean id="myXmlAspect" class="cn.tx.demo2.MyXmlAspect"/>
  • 在配置文件中完成aop的配置
    1   <!--配置AOP的增强-->
    2     <aop:config>
    3         <!--配置切面 = 切入点 + 通知组成-->
    4         <aop:aspect ref="myXmlAspect">
    5             <!--前置通知:UserServiceImpl的save方法执行前,会增强-->
    6             <aop:before method="log" pointcut="execution(public void cn.tx.demo2.UserServiceImpl.save())" />
    7         </aop:aspect>
    8     </aop:config>
  • 对增强进行测试

    package cn.tx.test;
    ?
    import cn.tx.demo2.UserService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext_demo2.xml")
    public class Demo2 {
    ?
        @Autowired
        private UserService userService;
    ?
        /**
         * 测试
         */
        @Test
        public void run1(){
            userService.save();
        }
    ?
    }
  • 切入点的表达式格式:
    • execution([修饰符] 返回值类型 包名.类名.方法名(参数))
    • 修饰符可以省略不写,不是必须要出现的。
    • 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。
    • 包名例如:com.tx.demo3.BookDaoImpl
      • 首先com是不能省略不写的,但是可以使用 * 代替
      • 中间的包名可以使用 * 号代替
      • 如果想省略中间的包名可以使用 ..
    • 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
    • 方法也可以使用 * 号代替
    • 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..
  • AOP的通知方式

     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:context="http://www.springframework.org/schema/context"
     5        xmlns:aop="http://www.springframework.org/schema/aop"
     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/context
    10                 http://www.springframework.org/schema/context/spring-context.xsd
    11                 http://www.springframework.org/schema/aop
    12                 http://www.springframework.org/schema/aop/spring-aop.xsd">
    13
    14     <!--bean管理-->
    15     <bean id="userService" class="cn.tx.demo1.UserServiceImpl" />
    16
    17     <!--=================编写AOP配置文件====================-->
    18     <!--先配置切面类-->
    19     <bean id="myXmlAspect" class="cn.tx.demo1.MyXmlAspect" />
    20
    21     <!--配置AOP的增强-->
    22     <aop:config>
    23         <!--正在配置切面,引入真正切面对象-->
    24         <aop:aspect ref="myXmlAspect">
    25             <!--配置的是前置通知:目标对象方法执行前,先增强。method="切面类中通知的方法" pointcut="切入点的表达式"-->
    26             <!--
    27                 切入点的表达式
    28                     execution() 写法是固定的
    29                     public  可以省略不写的
    30                     方法返回值   void int String * 通用的写法
    31                     包名  * 通用的写法
    32                     类名  * 推荐的写法 *ServiceImpl 例如:UserServiceImpl DeptServiceImpl
    33                     方法名称    *  推荐写法:save*
    34                     方法参数列表  .. == Object... obj Object类型的可变参数
    35                     <aop:before method="log" pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    36             -->
    37
    38             <!--
    39                 通知类型
    40                     前置通知:目标对象方法执行前,先增强。
    41                     <aop:before method="log" pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    42
    43                     最终通知:目标对象方法执行成功或者失败,都会增强。finally
    44                     <aop:after method="log" pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    45
    46                     后置通知:目标对象方法执行成功,才会增强。
    47                     <aop:after-returning method="log"  pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    48
    49                     异常通知:目标对象方法执行失败,才会增强。
    50                     <aop:after-throwing method="log"  pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    51
    52                     <aop:before method="begin" pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    53                     <aop:after-returning method="commit"  pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    54                     <aop:after-throwing method="rollback"  pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    55                     <aop:after method="close" pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    56
    57                     环绕通知:自己决定增强的位置。使用了环绕通知,目标对象的方法默认没有执行的,需要自己手动执行目标对象方法。
    58             -->
    59
    60             <aop:around method="logAroud"  pointcut="execution(* cn.tx.*.*ServiceImpl.save*(..))" />
    61
    62         </aop:aspect>
    63     </aop:config>
    64
    65 </beans>

    Spring的AOP技术-注解方式

  • 同样创建一个普通的Maven工程,导入坐标,编写接口,同上
  • 编写一个切面类,给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明

     1 package cn.tx.demo3;
     2 ?
     3 import org.aspectj.lang.annotation.Aspect;
     4 import org.aspectj.lang.annotation.Before;
     5 import org.springframework.stereotype.Component;
     6 ?
    12 @Component  // 把该类交给IOC去管理
    13 @Aspect     // 声明是切面类  == <aop:aspect ref="myXmlAspect">
    14 public class MyAnnoAspect {
    15 ?
    16     /**
    17      * 通知的方法
    18      */
    19     // @Before(value = "切入点的表达式")
    20     @Before(value = "execution(public * cn.tx.demo3.OrderServiceImpl.save(..))")
    21     public void log(){
    22         System.out.println("增强了...");
    23     }
    24 ?
    25 }
    26 ?
  • 配置文件中开启自动代理
    <aop:aspectj-autoproxy/>
  • 测试方法
     1
     2 package cn.tx.test;
     3 ?
     4 import cn.tx.demo2.UserService;
     5 import cn.tx.demo3.OrderService;
     6 import org.junit.Test;
     7 import org.junit.runner.RunWith;
     8 import org.springframework.beans.factory.annotation.Autowired;
     9 import org.springframework.test.context.ContextConfiguration;
    10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    11
    12
    13 @RunWith(SpringJUnit4ClassRunner.class)
    14 @ContextConfiguration("classpath:applicationContext_demo3.xml")
    15 public class Demo3 {
    16 ?
    17     @Autowired
    18     private OrderService orderService;
    19 ?
    20     /**
    21      * 测试
    22      */
    23     @Test
    24     public void run1(){
    25         orderService.save();
    26     }
    27 ?
    28 }
  • 通知类型注解
    1 @Before    -- 前置通知
    2
    3 ?    @AfterReturing    -- 后置通知
    4
    5 ?    @Around    -- 环绕通知(目标对象方法默认不执行的,需要手动执行)
    6
    7 ?    @After    -- 最终通知
    8
    9 ?    @AfterThrowing    -- 异常抛出通知
  • 纯注解的方式
    package cn.tx.demo3;
    ?
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    ?
    
    @Configuration      // 配置类
    @ComponentScan(value = "cn.tx.demo3")   // 扫描包
    @EnableAspectJAutoProxy     // 开启自动代理 == <aop:aspectj-autoproxy />
    public class SpringConfig {
    
    }

原文地址:https://www.cnblogs.com/LBJLAKERS/p/11750094.html

时间: 2024-07-31 07:32:26

解析Spring第三天(面向切面AOP)的相关文章

Spring基础(二)_面向切面(AOP)

面向切面编程 面向切面编程[AOP,Aspect Oriented Programming]:通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术.AOP 是 Spring 框架中的一个重要内容,利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 在 Spring 中,依赖注入管理和配置应用对象,有助于应用对象之间的解耦.而面向切面编程可以实现横切关注点与它们所影响的对象之间的解耦. 横切关注点:散布在应用中

Spring面向切面(AOP)

AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志.事务.权限等,Struts2的拦截器设计就是基于AOP的思想. AOP的基本概念 Aspect(切面):通常是一个类,里面可以定义切入点和通知 JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用. Advice(通知):AOP在特定的切入点上执行的增强处理,有before.after.afterReturning.afterThrowing.around Pointcut(切入点):AOP框架创

spring面向切面aop拦截器

spring中有很多概念和名词,其中有一些名字不同,但是从功能上来看总感觉是那么的相似,比如过滤器.拦截器.aop等. 过滤器filter.spring mvc拦截器Interceptor .面向切面编程aop,实际上都具有一定的拦截作用,都是拦截住某一个面,然后进行一定的处理. 在这里主要想着手的是aop,至于他们的比较,我想等三个都一一了解完了再说,因此这里便不做过多的比较. 在我目前的项目实践中,只在一个地方手动显示的使用了aop,那便是日志管理中对部分重要操作的记录. 据我目前所知,ao

Spring框架使用(控制反转,依赖注入,面向切面AOP)

参见:http://blog.csdn.net/fei641327936/article/details/52015121 Mybatis: 实现IOC的轻量级的一个Bean的容器 Inversion of control 控制反转:由容器控制程序之间的关系,不是程序代码操作 Depend Inject 依赖注入 Aspect oriented programming 面向切面编程 Spring能帮助我们根据配置文件创建及组装对象之间的依赖关系: Spring面向切面编程能帮助我们无耦合的实现日

Spring学习1_面向切面( AOP )实现原理

面向切面编程 (Aspect Oriented Programming,简称AOP) 是Spring的一个重要特性,其原理是采用动态代理方式实现. 下面通过一个Demo来模拟AOP实现 整个代码目录结构如下: 其中LogInterceptor类完成为所有Service方法添加日志记录的功能. 1.Dao层实现 package com.dao; public class UserDaoImpl implements UserDao { @Override public void save() {

三、面向切面编程

第八讲  面向切面编程--aop 1.aop:aspect oriented programming 面向切面编程 2.aop在spring中作用 提供声明式事务服务(声明式事务) 允许用户实现自定义切面 3.aop:在不改变原有代码的情况下增加新的功能. 传统的编程模式: Aop的编程模式:横向的编程 aop的好处:(代理的好处就是aop的好处) a)使得真实角色处理的业务更加纯粹,不再去关注一些公共的事情. b)公共的业务由代理来完成---实现业务的分工 c)公共业务发生扩展时变得更加集中和

Spring4面向切面AOP

AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术.AOP是OOP的补充,是spring框架中的一个重要内容.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率.AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高.动态织入则不需要改变目标模块.Spring框架实现了AOP,使用注解

Spring_面向切面(AOP)基础

努力不一定成功:但是放弃必定会失败. 面向切面编程 在软件开发中,散布于应用中多处的功能称为横切关注点.通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑之中).把这些横切关注点与业务逻辑分离正是面向切面编程(AOP)所要解决的问题. 如果要重用功能的话,最常见的面向对象技术是继承(inheritance)或委托(delegation).但是,如果在整个应用中都使用相同的基类,继承往往会导致一个脆弱的对象体系:而使用委托可能需要对委托对象进行复杂的调用

Spring学习总结之面向切面(AOP)

AOP术语 通知(advice):定义切面是什么以及什么时候使用 连接点(join point):应用在执行过程中能够插入切面的点 切点(pointcut):切点的定义会匹配通知所要织入的一个或多个连接点 切面(aspect):通知和切点的结合 引入(introduction):允许我们向现有的类添加新方法或属性 织入(weaving):把切面应用到目标对象并创建新的代理对象的过程 Spring使用AspectJ注解来声明通知方法 @After:通知方法会在目标方法返回或抛出异常后调用 @Aft