面向切面编程

Posted xuweiweiwoaini

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向切面编程相关的知识,希望对你有一定的参考价值。

1 AOP概述

1.1 什么是AOP?

  • AOP,全称是Aspect Oriented Programming,即面向切面编程。
  • 简单的说,AOP就是讲我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源代码的情况下,对我们已有的方法进行增强。

1.2 AOP的作用和优势

1.2.1 AOP的作用

  • 在程序运行期间,不修改源代码对已有方法进行增强。

1.2.2 AOP的优势

  • 减少重复代码。
  • 提高开发效率。
  • 维护方便。

1.3 AOP的实现方式

  • 使用动态代理技术。

 

2 Spring中的AOP

2.1 Spring中AOP的细节

2.1.1 AOP的相关术语

  • Joinpoint(连接点):所谓连接点是指那些被拦截的点。在Spring中,这些点指的是方法,因为SPring只支持方法类型的连接点。
  • Pointcut(切入点):所谓切入点是指我们要对那些Jointpoint进行拦截的定义。
  • Advice(通知/增强):
    • 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
    • 通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
  • Target(目标):代理的目标对象。
  • Weaving(织入):是指把藏青应用到目标对象来创建新的代理对象的过程。Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
  • Proxy(代理):一个类被AOP织入增强后,就产生了一个结果代理类。
  • Aspect(切面):是切入点和通知的结合。

2.2 基于XML的AOP配置

2.2.1 导入相关依赖jar包的maven坐标

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.0.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

2.2.2 LogUtils

package com.sunxiaping.spring5.log;

/**
 * 日志,即通知
 */
public class LogUtils {
    
    /**
     * 开始打印日志
     */

    public void startLog() {
        System.out.println("****开始打印日志****");
    }

    /**
     * 结束打印日志
     */

    public void endLog() {
        System.out.println("****结束打印日志****");
    }
}

2.2.3 编写业务层代码

  • IAccountService.java
package com.sunxiaping.spring5.service;

public interface IAccountService {

    /**
     * 新增
     */
    void save();

    /**
     * 更新
     */
    void update();


}
  • AccoutServiceImpl.java
package com.sunxiaping.spring5.service.impl;

import com.sunxiaping.spring5.service.IAccountService;

public class AccountServiceImpl implements IAccountService {

    @Override
    public void save() {
        System.out.println("新增");
    }

    @Override
    public void update() {
        System.out.println("根据");
    }
}

2.2.4 创建applicationContex.xml并配置

  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!-- 配置业务层   -->
    <bean id="accountService" class="com.sunxiaping.spring5.service.impl.AccountServiceImpl"/>
    <!-- 配置通知 -->
    <bean id="log" class="com.sunxiaping.spring5.log.LogUtils"></bean>

    <!-- 配置aop-->
    <aop:config>
        <!-- 配置切入点表达式-->
        <aop:pointcut id="pointcut" expression="execution(* com.sunxiaping.spring5.service.*.*(..))"/>
        <!--
            配置切面
            id:给切面提供一个唯一的id
            ref:引用配置好的通知类Bean的id
         -->
        <aop:aspect ref="log">
            <!-- 前置通知 -->
            <aop:before method="startLog" pointcut-ref="pointcut"/>
            <!-- 后置通知 -->
            <aop:after method="endLog" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

2.2.5 测试

  • 示例:
package com.sunxiaping;

import com.sunxiaping.spring5.service.IAccountService;
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(locations = "classpath:applicationContext.xml")
public class spring5Test {

    @Autowired
    private IAccountService accountService;

    @Test
    public void test() {
        accountService.save();
    }

}

2.3 基于注解的AOP配置

2.3.1 业务层配置注解

  • IAccountService.java
package com.sunxiaping.spring5.service;

public interface IAccountService {

    /**
     * 新增
     */
    void save();

    /**
     * 更新
     */
    void update();


}
  • AccountServiceImpl.java
package com.sunxiaping.spring5.service.impl;

import com.sunxiaping.spring5.service.IAccountService;
import org.springframework.stereotype.Service;

@Service
public class AccountServiceImpl implements IAccountService {

    @Override
    public void save() {
        System.out.println("新增");
    }

    @Override
    public void update() {
        System.out.println("根据");
    }
}

2.3.2 配置通知

  • 示例:
package com.sunxiaping.spring5.log;

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
@Aspect //表明是一个通知类
public class LogUtils {

    @Pointcut("execution(* com.sunxiaping.spring5.service.*.*(..))")
    public void pointcut() {

    }


    /**
     * 开始打印日志
     */
    @Before("pointcut()")
    public void startLog() {
        System.out.println("****开始打印日志****");
    }

    /**
     * 结束打印日志
     */
    @After("pointcut()")
    public void endLog() {
        System.out.println("****结束打印日志****");
    }
}

2.3.3 创建并配置applicationContext.xml

  • applicationContex.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">


    <context:component-scan base-package="com.sunxiaping.spring5"/>

    <!--开启Spring对注解AOP的支持-->
    <aop:aspectj-autoproxy/>

</beans>

2.3.4 测试

  • 示例:
package com.sunxiaping;

import com.sunxiaping.spring5.service.IAccountService;
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(locations = "classpath:applicationContext.xml")
public class spring5Test {

    @Autowired
    private IAccountService accountService;

    @Test
    public void test() {
        accountService.save();
    }

}

2.4 基于纯注解的AOP配置

2.4.1 配置业务层注解

  • IAccountService.java
package com.sunxiaping.spring5.service;

public interface IAccountService {

    /**
     * 新增
     */
    void save();

    /**
     * 更新
     */
    void update();


}
  • AccountServiceImpl.java
package com.sunxiaping.spring5.service.impl;

import com.sunxiaping.spring5.service.IAccountService;
import org.springframework.stereotype.Service;

@Service
public class AccountServiceImpl implements IAccountService {

    @Override
    public void save() {
        System.out.println("新增");
    }

    @Override
    public void update() {
        System.out.println("根据");
    }
}

2.4.2 配置通知

  • LogUtils.java
package com.sunxiaping.spring5.log;

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
@Aspect //表明是一个通知类
public class LogUtils {

    @Pointcut("execution(* com.sunxiaping.spring5.service.*.*(..))")
    public void pointcut() {

    }


    /**
     * 开始打印日志
     */
    @Before("pointcut()")
    public void startLog() {
        System.out.println("****开始打印日志****");
    }

    /**
     * 结束打印日志
     */
    @After("pointcut()")
    public void endLog() {
        System.out.println("****结束打印日志****");
    }
}

2.4.3 配置SpringConfiguration.java文件

  • SpringConfiguration.java
package com.sunxiaping.spring5.config;

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

@Configuration
@ComponentScan(basePackages = "com.sunxiaping.spring5")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}

2.4.4 测试

  • 示例:
package com.sunxiaping;

import com.sunxiaping.spring5.config.SpringConfiguration;
import com.sunxiaping.spring5.service.IAccountService;
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(classes = SpringConfiguration.class)
public class spring5Test {

    @Autowired
    private IAccountService accountService;

    @Test
    public void test() {
        accountService.save();
    }

}

 

以上是关于面向切面编程的主要内容,如果未能解决你的问题,请参考以下文章

java怎么运用切面编程生成日志

面向切面编程

Spring的AOP面向切面编程

面向切面编程

Spring面向切面编程

Spring的AOP面向切面编程