文档章节

spring-101-springAOP

haoran_10
 haoran_10
发布于 2016/07/15 16:44
字数 1551
阅读 14
收藏 1
点赞 0
评论 0

前言:

在很多场景下有一个共同的业务模块。比如用户在网站购物时,加入商品到购物车,下单,支付,等等,但是所有的业务都需要打日志,但是每个业务重写一遍日志又比较麻烦。此时springAOP可以适用这样的情况。

AOP(Aspect Oriented Programming),即面向切面编程(也叫面向方面编程,面向方法编程)。其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能。像日志记录,事务处理,权限控制等功能,都可以用AOP来“优雅”地实现,使这些额外功能和真正的业务逻辑分离开来,软件的结构将更加清晰。

springAOP概念较多,但是最为关键的有2个:

  • Advice

        通知,多个业务模块都用到一个共同的功能,那么这个共同的功能,比如打日志,这个就是通知。
  • Pointcut

        切入点,多个业务模块都用到一个共同的功能,那么这个多个业务模块,比如加入商品到购物车,这个就是切入点。

spring为了方便,对这两个进行了组合

  • Advisor

        这个其实是Advice和Pointcut的组合,Advice和Pointcut组成的独立的单元。
    也就是说,多个业务模块都用到一个共同的功能,那么这个整体就叫Advisor

就依用户网站购物,加入商品到购物车,下单,支付都用到了加入日志为例子做一个DEMO。

1.用户多业务场景

用户在网站购物三个业务模块,加入商品到购物车,下单,支付代码,如下,代码清单1:

package wang.conge.springdemo.aop.service;

import org.springframework.stereotype.Component;

import wang.conge.springdemo.aop.annotation.AopLogAnnotation;

@Component
public class UserService {
    
    @AopLogAnnotation
    public void addCar() {
        System.out.println("加入购物车");
    }
    
    @AopLogAnnotation
    public void createOrder() {
        System.out.println("下单");
    }
    
    @AopLogAnnotation
    public void pay() {
        System.out.println("付款");
    }
}

代码清单1 用到了注解作为切入点的最小单元,先列出来,下面说明,代码清单2:

package wang.conge.springdemo.aop.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AopLogAnnotation {
    String value() default "";
}

2.共同业务模块

用户在网站购物三个业务模块,加入商品到购物车,下单,支付代码,但是都用到了加入日志,如下,代码清单3:

package wang.conge.springdemo.aop.service;

import java.lang.reflect.Method;
import java.util.Optional;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.stereotype.Component;

import wang.conge.springdemo.aop.annotation.AopLogAnnotation;

@Component
public class CommonLogAdvisor extends AbstractPointcutAdvisor{
    private static final long serialVersionUID = 1L;
    
    @Override
    public Pointcut getPointcut() {
        return new StaticMethodMatcherPointcut() {
            
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                //TODO matches targetClass 
                //if(targetClass matches AopTargetClass) return true;
                
                //TODO matches method 
                //if(method matches AopMethod) return true;
                
                if(method.isAnnotationPresent(AopLogAnnotation.class)) {
                    return true;
                }
                
                return false;
            }
            
        };
    }

    @Override
    public Advice getAdvice() {
        return new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                Object ret = null;
                try {
                    //TODO before
                    System.out.println("=====SpringAopAdvisor-调用前before逻辑===");
                    
                    ret = invocation.proceed();
                    
                    //TODO after
                    System.out.println("=====SpringAopAdvisor-调用后after逻辑===");
                    
                    return ret;
                } catch (Exception e) {
                    //TODO throw
                    System.out.println("=====SpringAopAdvisor-调用异常throw逻辑===");
                    return Optional.empty();
                } finally {
                    //TODO finally
                    System.out.println("=====SpringAopAdvisor-调用最终结束逻辑===");
                }
            }
        };
    }
    
}

下面对代码说明,为整个DEMO中核心代码:

  • public Advice getAdvice() ;该方法就是返回共同的业务所做的事情,在业务调用时就会在合适的逻辑之前,或之后,或发生异常,去完成相应的共同逻辑处理。
  • public Pointcut getPointcut() ; 该方法返回拦截业务的规则,事实上,加入商品到购物车,下单,支付并不是切入点,而加入商品到购物车,下单,支付这几个业务怎样在哪里加入共同日志的方式,或者规则,才叫切入点。方法里利用注解的方式,如果方法上注解了AopLogAnnotation,就会拦截,否则不拦截。也可以进进一步从类的Class做拦截的规则,这个看具体业务拦截的方式了。

3.配置代码

剩下的代码则是对上述代码进行组织运行了。
配置代码,启用EnableAspectJAutoProxy支持。代码清单4:

package wang.conge.springdemo.aop.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
@ComponentScan("wang.conge.springdemo.aop.service")
public class AppConfig {
    
}

运行主代码,代码清单5:

package wang.conge.springdemo.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import wang.conge.springdemo.aop.config.AppConfig;
import wang.conge.springdemo.aop.service.UserService;

public class AppStart {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        
        UserService myService = applicationContext.getBean(UserService.class);
        myService.addCar();
        
        myService.createOrder();
    }

}

OK,整个DEMO就结束了,紧紧抓住AOP的主题思想:

  • 多个业务有共同功能,多个业务切入点,也就是被拦截的地方,或者拦截这些多个业务的规则
  • 多个业务共同的功能,也就是该共同功能所做的事情。

上述代码是以springAOP做实例,事实上spring也支持aspectj ,但是运行的方式还是根据代理的形式。
而spring实现AOP的技术,主要分为两大类:

一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。


如果要是原生的aspectj 还是比较复杂,牵扯到织入的细节。aspectj是aop的Java实现方案。下面是几点关于aspectj的描述:

  • AspectJ是一个代码生成工具(CodeGenerator),其中AspectJ语法就是用来定义代码生成规则的语法。基于自己的语法编译工具,编译的结果是Java Class文件,运行的时候classpath需要包含AspectJ的一个jar文件(Runtime lib),支持编译时织入切面,即所谓的CTW机制,可以通过一个Ant或Maven任务来完成这个操作。
  • AspectJ有自己的类装载器,支持在类装载时织入切面,即所谓的LTW机制。使用AspectJ LTW有两个主要步骤,第一,通过JVM的-javaagent参数设置LTW的织入器类包,以代理JVM默认的类加载器;第二,LTW织入器需要一个 aop.xml文件,在该文件中指定切面类和需要进行切面织入的目标类
  • AspectJ同样也支持运行时织入,运行时织入是基于动态代理的机制。(默认机制)

附录1,AOP详细概念:

附录2,spring aop官方网站介绍资料:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

© 著作权归作者所有

共有 人打赏支持
haoran_10
粉丝 25
博文 88
码字总数 80846
作品 0
杭州
程序员
Spring系列之Spring框架和SpringAOP集成过程分析(十)

在开始这个系列之前大家先想一下我们是怎么在项目中使用SpringAOP的(这里的分析都是基于AspectJ注解的)。我们需要在我们的Spring配置文件中引入SpringAOP的命名空间和标签,然后定义切面Bea...

木叶之荣 ⋅ 06/18 ⋅ 0

Spring AOP就是这么简单啦

前言 只有光头才能变强 上一篇已经讲解了Spring IOC知识点一网打尽!,这篇主要是讲解Spring的AOP模块~ 之前我已经写过一篇关于AOP的文章了,那篇把比较重要的知识点都讲解过了一篇啦:Sprin...

Java3y ⋅ 05/24 ⋅ 0

Spring Boot 2.0 动态数据源快速启动器 1.3.0 发布

dynamic-datasource-spring-boot-starter 升级到1.3.0版本,dynamic-datasource-spring-boot-starter 是 Spring Boot 2.0 的动态数据源快速启动器。 项目及文档地址:https://gitee.com/bao......

小锅盖 ⋅ 05/08 ⋅ 0

JavaWeb springAOP的问题

项目是Spring+SpringMVC+Ibatis的,使用AOP的时候,能够切入到Controller里面 Controller AOP 上面这个是可以成功运行的 然后,我想再切入到封装了Ibatis的类的方法,发现无效 封装 切入 求解...

CodeZero ⋅ 2017/02/06 ⋅ 0

spring-boot整合spring-session,使用redis共享

本文讲述spring-boot工程中使用spring-session机制进行安全认证,并且通过redis存储session,满足集群部署、分布式系统的session共享。 java工程中,说到权限管理和安全认证,我们首先想到的...

louieSun ⋅ 05/13 ⋅ 0

springboot + shiro 权限注解、请求乱码解决、统一异常处理

springboot + shiro 权限注解、请求乱码解决、统一异常处理 前篇 后台权限管理系统 相关: spring boot + mybatis + layui + shiro后台权限管理系统 springboot + shiro之登录人数限制、登录...

wyait ⋅ 06/06 ⋅ 0

早前学习Java记录

Spring 对 iBATIS 的支持】 Spring 通过 DAO 模式,提供了对 iBATIS 的良好支持。 SqlMapClient:是 iBATIS 中的主要接口,通过 xml 配置文件可以让 Spring 容器来管理 SqlMapClient 对象的创...

大风厂蔡成功 ⋅ 2016/07/10 ⋅ 0

第二章——Spring Boot启动器与依赖管理

强烈推荐选择支持依赖管理和可以发布到“Maven中央”仓库的构建系统。推荐使用Maven或Gradle。Spring Boot可以使用其他构建系统(例如,Ant),但支持得并不是很好。 1 依赖管理 Spring Boo...

Leech ⋅ 02/04 ⋅ 0

spring之AOP(面向切面编程)

一、简介 何为AOP,通俗的将就是给某些方法执行之前、执行之后等动作发生的时候执行某些操作,在执行这些操作的时候可以获取执行方法的相关信息,简化程序开发中总是重复的东西,比如方法入参...

图样图森破 ⋅ 2016/12/26 ⋅ 0

Spring中涉及的设计模式总结

Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式:BeanFactory。 Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是...

caoxiaohong1005 ⋅ 04/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

win10怎么彻底关闭自动更新

win10自带的更新每天都很多,每一次下载都要占用大量网络,而且安装要等得时间也蛮久的。 工具/原料 Win10 方法/步骤 单击左下角开始菜单点击设置图标进入设置界面 在设置窗口中输入“服务”...

阿K1225 ⋅ 今天 ⋅ 0

Elasticsearch 6.3.0 SQL功能使用案例分享

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3.0 官方新推出的SQL检索插件非常不错,本文一个实际案例来介绍其使用方法。 1.代码中的sql检索 @Testpu...

bboss ⋅ 今天 ⋅ 0

informix数据库在linux中的安装以及用java/c/c++访问

一、安装前准备 安装JDK(略) 到IBM官网上下载informix软件:iif.12.10.FC9DE.linux-x86_64.tar放在某个大家都可以访问的目录比如:/mypkg,并解压到该目录下。 我也放到了百度云和天翼云上...

wangxuwei ⋅ 今天 ⋅ 0

PHP语言系统ZBLOG或许无法重现月光博客的闪耀历史[图]

最近在写博客,希望通过自己努力打造一个优秀的教育类主题博客,名动江湖,但是问题来了,现在写博客还有前途吗?面对强大的自媒体站点围剿,还有信心和可能型吗? 至于程序部分,我选择了P...

原创小博客 ⋅ 今天 ⋅ 0

IntelliJ IDEA 2018.1新特性

工欲善其事必先利其器,如果有一款IDE可以让你更高效地专注于开发以及源码阅读,为什么不试一试? 本文转载自:netty技术内幕 3月27日,jetbrains正式发布期待已久的IntelliJ IDEA 2018.1,再...

Romane ⋅ 今天 ⋅ 0

浅谈设计模式之工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻...

佛系程序猿灬 ⋅ 今天 ⋅ 0

Dockerfile基础命令总结

FROM 指定使用的基础base image FROM scratch # 制作base image ,不使用任何基础imageFROM centos # 使用base imageFROM ubuntu:14.04 尽量使用官方的base image,为了安全 LABEL 描述作...

ExtreU ⋅ 昨天 ⋅ 0

存储,对比私有云和公有云的不同

导读 说起公共存储,很难不与后网络公司时代的选择性外包联系起来,但尽管如此,它还是具备着简单和固有的可用性。公共存储的名字听起来也缺乏专有性,很像是把东西直接堆放在那里而不会得到...

问题终结者 ⋅ 昨天 ⋅ 0

C++难点解析之const修饰符

C++难点解析之const修饰符 c++ 相比于其他编程语言,可能是最为难掌握,概念最为复杂的。结合自己平时的C++使用经验,这里将会列举出一些常见的难点并给出相应的解释。 const修饰符 const在c...

jackie8tao ⋅ 昨天 ⋅ 0

聊聊spring cloud netflix的HystrixCommands

序 本文主要研究一下spring cloud netflix的HystrixCommands。 maven <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-clo......

go4it ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部