文档章节

Spring系列教程六:AOP详细讲解

我叫小糖主
 我叫小糖主
发布于 05/19 22:37
字数 2048
阅读 23
收藏 3

AOP 概述

什么是 AOP

AOP:全称是 Aspect Oriented Programming 即:面向切面编程。

AOP技术是对OOP技术的一种延伸,AOP是面向纵向,OOP是面向横向。简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的
基础上,对我们的已有方法进行增强。

AOP 的作用以及优势

作用:在程序运行期间,不修改源码对已有方法前面和后面进行增强。
优势:减少重复代码、提高开发效率、维护方便

AOP实现方式

使用动态代理技术

基于xml方式的aop配置

实现步骤如下

导入spring-aop jar包

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        下面几个是必须要导的包
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>

需要增强方法的StudentDao类,和写增强方法的Userlogger类

package com.ithema.jdbc.dao;

public class StudentDao {
    //在执行add方法之前执行日志

    public int add(int a,int b){
        System.out.println("执行了add方法");
        return a+b;
    }
    public  int jian(int a,int b){
        System.out.println("执行了减法");
        return a-b;
    }
   /* public void testexe(){
        int i=10/0;
    }*/
}
package com.ithema.jdbc.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Arrays;

/**
 * 切面:
 * 前置增强、后置增强、异常增强、最终增强、环绕增强
 *
 * Spring aop完全是用动态代理实现的
 * 但是动态代理又有两种,jdkk代理,cglib代理(更强大一些)
 * spirng aop:默认使用jdk代理,但是你的目标类没接口,会自动切换到cglib代理
 */
public class UserLogger {

    //在目标方法调用之前执行该方法
    Logger logger=Logger.getLogger(UserLogger.class);
    public void before(JoinPoint jp){
        logger.info("前置增强,目标类名"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "参数为:"+ Arrays.toString(jp.getArgs()));
    }
    //在目标方法调用之后执行该方法
    //当方法抛出异常就不会执行了,所有该方法不适合做日志收集,因为发生了异常不执行该方法无法将日志保存下来
    //所有后置增强用的很少
    public void after(JoinPoint jp,Object result){
        logger.info("后置增强,执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "方法,结果为:"+ result);
    }
    //在方法抛出异常后就会增强、没有异常就不会执行、如果用户try-catch,也不会增强
    //执行错误的话,非常适合该增强(异常增强)
    //Java异常体系,根类是Throwable
    public void afterThorwing(JoinPoint jp,Throwable e){
        logger.info("异常增强,执行类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "方法抛出异常:"+e.getMessage());
    }
    //最终增强:无论是否有异常,都会执行,类似与finally,可以或者是认为是后置增强的升级版
    public void finalafter(JoinPoint jp){
        logger.info("最终增强:执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName());
    }
    //环绕增强,集合了前置添加后置,并且更加强大、当执行方法发生异常后面的就不执行了
    //1、可以修改方法的参数 2、也可以修改方法的返回值( return result)
    public Object around(ProceedingJoinPoint jp)throws Throwable{
        Object [] args=jp.getArgs();//获取方法参数
        //可以修改方法的参数
        //args = new Object[]{20,1};
        logger.info("环绕增强:方法为:"+jp.getArgs());
        Object result=jp.proceed();//执行目标方法
        //也可以修改方法的返回值
        //return 100;
        return result;
    }
}

配置aop约束到配置文件中,并实现ioc配置

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       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就是一个对象>
    <bean id="studentDao" class="com.ithema.jdbc.dao.StudentDao">
    </bean>
    <bean id="userLogger" class="com.ithema.jdbc.aop.UserLogger">
    </bean>

使用 aop:aspect 配置切面,使用 aop:pointcut  配置切入点表达式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       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="studentDao" class="com.ithema.jdbc.dao.StudentDao">
    </bean>
    <bean id="userLogger" class="com.ithema.jdbc.aop.UserLogger">
    </bean>
    <!--aop配置,实现dao里面的方法前后增强-->
    <aop:config>
        <!--定义切入点-->
        <!--标准写法格式:(返回值:全类名(包名.类名.方法名(参数类型列表))-->
        <aop:pointcut id="pointcut" expression="execution(* com.ithema.jdbc..*.*(..))"></aop:pointcut>
        <!--组织增强-->
        <!--切面ref:应用其他bean对象-->
        <aop:aspect ref="userLogger">
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>
            <aop:after-returning method="after" pointcut-ref="pointcut" returning="result"></aop:after-returning>
            <aop:after-throwing method="afterThorwing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
            <aop:after method="finalafter" pointcut-ref="pointcut"></aop:after>
            <aop:around method="around" pointcut-ref="pointcut"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

基于注解方式的aop配置

导入spring-aop jar包

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        下面几个是必须要导的包
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>

配置aop约束到配置文件中,在配置文件中指定 spring 要扫描的包,开启 spring 对注解 AOP 的支持

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!--告诉Spring容器在创建的时候要扫描包,配置所需要的标签不在bean约束中,而是
    在一个叫做context的空降名称和约束中-->
    <context:component-scan base-package="com.bdqn"></context:component-scan>
   <!-- 开启注解aop-->
   <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

使用注解配置增强方法

package com.bdqn.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect
public class UserLogger {

    //在目标方法调用之前执行该方法
    Logger logger=Logger.getLogger(UserLogger.class);
    //定义切点
    @Pointcut("execution(* com.bdqn.aop..*.*(..))")
    public void pointcut(){}
    @Before("pointcut()")
    public void before(JoinPoint jp){
        logger.info("前置增强,目标类名"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "参数为:"+ Arrays.toString(jp.getArgs()));
    }
    //在目标方法调用之后执行该方法
    //当方法抛出异常就不会执行了,所有该方法不适合做日志收集,因为发生了异常不执行该方法无法将日志保存下来
    //所有后置增强用的很少
    public void after(JoinPoint jp,Object result){
        logger.info("后置增强,执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "方法,结果为:"+ result);
    }
    //在方法抛出异常后就会增强、没有异常就不会执行、如果用户try-catch,也不会增强
    //执行错误的话,非常适合该增强(异常增强)
    //Java异常体系,根类是Throwable
    @AfterThrowing(pointcut = "execution(* com.bdqn.aop..*.*(..))",throwing = "e")
    public void afterThorwing(JoinPoint jp,Throwable e){
        logger.info("异常增强,执行类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+
                "方法抛出异常:"+e.getMessage());
    }
    //最终增强:无论是否有异常,都会执行,类似与finally,可以或者是认为是后置增强的升级版
    @After("execution(* com.bdqn.aop..*.*(..))")
    public void finalafter(JoinPoint jp){
        logger.info("最终增强:执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName());
    }
    //环绕增强,集合了前置添加后置,并且更加强大、当执行方法发生异常后面的就不执行了
    //1、可以修改方法的参数 2、也可以修改方法的返回值( return result)
    @Around("execution(* com.bdqn.aop..*.*(..))")
    public Object around(ProceedingJoinPoint jp)throws Throwable{
        Object [] args=jp.getArgs();//获取方法参数
        //可以修改方法的参数
        //args = new Object[]{20,1};
        logger.info("环绕增强:方法为:"+jp.getArgs());
        Object result=jp.proceed();//执行目标方法
        //也可以修改方法的返回值
        //return 100;
        return result;
    }
}

使用spring整合junit4的方式写测试类

package com.bdqn.test;

import com.bdqn.dao.StudentDao;
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 Testaop {
    @Autowired
    private StudentDao studentDao;
    @Test
    public  void testaop(){
        studentDao.add();
        studentDao.jian(3,1);
        System.out.println("执行了减法,结果为:");
    }
}

 

© 著作权归作者所有

我叫小糖主
粉丝 6
博文 43
码字总数 49875
作品 0
大渡口
私信 提问
Spring经典视频教程大集合

Spring经典视频教程大集合 Spring是一个开源框架,它由RodJohnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Sprin...

IT小白白
2012/10/08
0
0
spring boot框架学习5-spring boot的web开发(1)

本章节主要内容: 通过前面的学习,我们了解并快速完成了spring boot第一个应用。spring boot企业级框架,那么spring boot怎么读取静态资源?如js文件夹,css文件以及png/jpg图片呢?怎么自定...

凯哥java
2017/11/01
0
0
Spring AOP 源码分析系列文章导读

简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解。在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅读了 AOP ...

java高级架构牛人
2018/06/21
0
0
springboot 中使用事务

直接在service 层的方法上加上@Transactional 注解就ok。 注意事项: 1、Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运行期异常(java.lang.RuntimeException及其子类)和 ...

不开心时不要学习
2018/01/12
0
2
分布式事务系列(1.2)Spring的事务体系

1 系列目录 - 分布式事务系列(开篇)提出疑问和研究过程- 分布式事务系列(1.1)Spring事务管理器PlatformTransactionManager源码分析- 分布式事务系列(1.2)Spring事务体系- 分布式事务系...

乒乓狂魔
2015/05/18
0
4

没有更多内容

加载失败,请刷新页面

加载更多

FPGA 设备 USB Platform Cable USB

lsusbFuture Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC

MtrS
今天
4
0
lua web快速开发指南(6) - Cache、DB介绍

"数据库"与"缓存"的基本概念 数据库与缓存是服务端开发人员的必学知识点. 数据库 "数据库"是一种信息记录、存取的虚拟标记地点的集合统称. 比如现实生活中, 我们经常会用到文件柜、书桌等等数...

水果糖的小铺子
今天
7
0
Oracle分页查询语句的写法

Oracle分页查询语句的写法 Oracle分页查询语句使我们最常用的语句之一,下面就为您介绍的Oracle分页查询语句的用法,Oracle分页查询语句基本上可以按本文给出的格式来进行套用。   Oracle分...

康师傅
昨天
5
0
java并发图谱

1527
昨天
2
0
Mybatis之拦截器Interceptor

使用mybatis时用PageHelper进行分页,用到了PageInterceptor,借此了解下mybatis的interceptor。Mybatis的版本是3.4.6,MybatisHelper的版本是5.1.3。 1、PageInterceptor 先上一段代码,如下...

克虏伯
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部