Spring AOP介绍(一)之 Spring AOP 基础介绍

spring.png

Spring AOP介绍(一)之 Spring AOP 基础介绍

AOP是什么?

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。与OOP对比,AOP面向切面,传统的OOP开发中,代码逻辑是自上而下的,在这些自上而下的过程中,会产生一些横切性的问题,这些横切性的问题和我们的主业务逻辑关系不大,会散落在代码的各个地方,造成难以维护,AOP的变成思想就是把业务逻辑和横切的问题进行分离,从而达到解耦的目的,提到代码的可重用性与开发效率。

可以看下这个图:

spring aop场景.png

AOP的应用场景有哪些?

如上图中显示的:

  • 日志记录
  • 权限验证
  • 事务管理
  • 等等
Spring对于AOP是怎样实现的呢?
  • JDK动态代理(接口实现)

JDK原生动态代理是Java原生支持的,不需要任何外部依赖,但是它只能基于接口进行代理

  • CGLIB代理(继承)

CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,
它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。

编译时期的织入还是运行时期的织入?

两者都是在运行时期织入(后面有源码介绍)

初始化时期织入还是获取对象时期织入?

通过源码分析,可以知道是在初始化时期织入(后面有源码介绍)

Spring AOP和AspectJ的关系是什么?

对于Spring AOP来说,AOP是实现的目标,AspectJ是实现的手段,类似的还有IOC(Inversion of Control 控制反转)是目标,实现的手段是DI(Dependency Injection 依赖注入)。

Spring AOP提供两种编程风格

  • @AspectJ support (利用aspectj的注解)
  • Schema-based AOP support (xml aop:config 命名空间)
Spring AOP应用

让我们首先了解一些AOP概念和术语。

概念描述
Join point(连接点)目标对象中的方法,类似数据库表中的一条记录
PointCut(切点)表示连接点的集合,类似数据库中的表
Advice(通知)通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
Aspect(切面)切点、连接点、通知等的载体,它们加起来就是一个切面
Target object(目标对象)包含连接点的对象,也被称作被通知或被代理对象
AOP proxy(AOP 代理对象)AOP创建的对象,包含通知
Weaving(织入)把代理逻辑加入到目标对象的过程,叫做织入
Before advice(前置通知)前置通知
After returning advice(后置通知)后置通知
Around advice(环绕通知)前后都有,最常用的一种通知
简单代码演示

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.demo.spring</groupId>
  <artifactId>spring-aop</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>spring-aop Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.1.5.RELEASE</version>
      </dependency>

      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.9</version>
      </dependency>


      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
  </dependencies>
</project>

com.demo.spring.dao.TestDao

package com.demo.spring.dao;

import org.springframework.stereotype.Component;

/**
 * PACKAGE_NAME
 *
 * @author Zyy
 * @date 2019/3/4 23:03
 */
@Component
public class TestDao {

    public void query(){
        System.out.println("dao-query ...");
    }
}

com.demo.spring.config.AppConfig

package com.demo.spring.config;

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

/**
 * com.demo.spring.config
 *
 * @author Zyy
 * @date 2019/3/4 23:05
 */
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.demo.spring")
public class AppConfig {
}

com.demo.spring.config.AspectJTest

package com.demo.spring.config;

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;

/**
 * com.demo.spring.config
 *
 * @author Zyy
 * @date 2019/3/4 23:36
 */
@Aspect
@Component
public class AspectJTest {

    @Pointcut("execution(* com.demo.spring.dao.*.*(..))")
    public void pointCut(){
        System.out.println("point cut");
    }

    @After("com.demo.spring.config.AspectJTest.pointCut()")
    public void after(){
        System.out.println("after advice");
    }

    @Before("com.demo.spring.config.AspectJTest.pointCut()")
    public void before(){
        System.out.println("before advice");
    }
}

com.demo.spring.test.AopTest

package com.demo.spring.test;

import com.demo.spring.config.AppConfig;
import com.demo.spring.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * com.demo.spring.test
 *
 * @author Zyy
 * @date 2019/3/4 23:07
 */
public class AopTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        TestDao dao = context.getBean(TestDao.class);
        dao.query();
    }
}

运行结果:

before advice
dao-query ...
after advice

欢迎留言进行讨论:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值