Spring基于AspectJ的AOP的开发——注解

源码:https://gitee.com/kszsa/dchart

一, AspectJ的概述:

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

Spring为了简化自身的AOP的开发,将AspectJ拿过来作为Spring自身一个AOP的开发.

二, Spring AspectJ开发实例

2.1 开发所需jar包

maven中相关包引入

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
<!-- aspectJ依赖包 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

2.2 AspectJ 注解开发规范

2.2.1 AspectJ的切入点:

    //统一管理切入点的表达式.
    @Pointcut(value="execution(* com.dchart.aop.service.CustomerService+.find(..))")
    private void myPointcut1(){}//这个类没有实际用途, 只是为了@Pointcut 注解

2.2.2 @AspectJ提供不同的通知类型

@Before 前置通知,相当于BeforeAdvice

  在执行目标方法之前完成一个操作,获得到切入点信息.

@Before(value="execution(* com.dchart.aop.service.CustomerService+.save(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知============"+joinPoint);
    }

@AfterReturning 后置通知,相当于AfterReturningAdvice

在目标方法执行之后完成一个操作,获得方法的返回值.
@AfterReturning(value="execution(* com.dchart.aop.service.CustomerService+.update(..))",returning="result")
    public void afterReturn(Object result){
        System.out.println("后置通知============"+result);
    }

@Around 环绕通知,相当于MethodInterceptor

在目标方法执行的前和执行后完成一个操作,阻止目标方法执行.
@Around(value="execution(* com.dchart.aop.service.CustomerService+.delete(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前通知==========");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后通知==========");
        return obj;
    }

@AfterThrowing抛出通知,相当于ThrowAdvice

在目标方法出现异常的时候,完成一个操作.获得异常信息.
@AfterThrowing(value="CustomerServiceAspect.myPointcut1()",throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("异常抛出通知========="+e.getMessage());
    }

@After 最终final通知,不管是否异常,该通知都会执行

在目标方法任何情况下都会执行的操作.相当于finally中的代码.
@After(value="CustomerServiceAspect.myPointcut1()")
    public void after(){
        System.out.println("最终通知===========");
    }

2.2.3 通过配置启用@AspectJ切面

1、开启AspectJ的自动代理

<?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"
    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-4.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 开启AspectJ自动代理 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

2、对应的切面类添加注解

2.2.4 Aspect和Advisor的区别:

Advisor :传统的切面.传统切面一般都是由一个切入点和一个通知的组合.
Aspect :真正意义上的切面.由多个切入点和多个通知的组合.

2.2.5 在通知中通过value属性定义切点

通过execution函数,可以定义切点的方法切入
语法:
  execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
例如
  匹配所有类public方法 execution(public * *(..))
  匹配指定包下所有类方法 execution(* cn.itcast.dao.*(..)) 不包含子包
  execution(* cn.itcast.dao..*(..)) ..*表示包、子孙包下所有类
  匹配指定类所有方法 execution(* cn.itcast.service.UserService.*(..))
  匹配实现特定接口所有类方法 execution(* cn.itcast.dao.GenericDAO+.*(..))
  匹配所有save开头的方法 execution(* save*(..))

2.3 Spring AspctJ 基于注解模式的开发例子

定义接口CustomerService.java

package com.dchart.aop.service;

public interface CustomerService {
    
    public void save();

    public Integer update();

    public void delete();

    public void find();

}

接口实现

CustomerServiceImp.java
package com.dchart.aop.service.imp;

import com.dchart.aop.service.CustomerService;

public class CustomerServiceImp implements CustomerService {

     @Override
        public void save() {
            System.out.println("保存客户...");
        }

        @Override
        public Integer update() {
            System.out.println("修改客户...");
            return 100;
        }

        @Override
        public void delete() {
            System.out.println("删除客户...");
        }

        @Override
        public void find() {
            System.out.println("查询客户...");
           // int d = 1 / 0;
        }

}

编写切面类

CustomerServiceAspect.java

package com.dchart.aop.service.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class CustomerServiceAspect {
    
    //统一管理切入点的表达式.
    @Pointcut(value="execution(* com.dchart.aop.service.CustomerService+.find(..))")
    private void myPointcut1(){}//这个类没有实际用途, 只是为了@Pointcut 注解
    
    
    @Before(value="execution(* com.dchart.aop.service.CustomerService+.save(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置通知============"+joinPoint);
    }
    
    @AfterReturning(value="execution(* com.dchart.aop.service.CustomerService+.update(..))",returning="result")
    public void afterReturn(Object result){
        System.out.println("后置通知============"+result);
    }
    
    @Around(value="execution(* com.dchart.aop.service.CustomerService+.delete(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前通知==========");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后通知==========");
        return obj;
    }
    
    @AfterThrowing(value="CustomerServiceAspect.myPointcut1()",throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("异常抛出通知========="+e.getMessage());
    }
    
    @After(value="CustomerServiceAspect.myPointcut1()")
    public void after(){
        System.out.println("最终通知===========");
    }

    

}

单元测试类CustomerServiceImpTest.java

package com.dchart.aop.service.imp;

import static org.junit.Assert.*;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.dchart.aop.service.CustomerService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring_aop.xml")
public class CustomerServiceImpTest {
    
    @Resource(name="customerService")
    private CustomerService customerService;

    @Test
    public void test() {
        customerService.save();
        customerService.update();
        customerService.delete();
        customerService.find();
    }

}

Spring 配置文件:spring_aop.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"
    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-4.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 开启AspectJ自动代理 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 目标对象 -->
    <bean id="customerService" class="com.dchart.aop.service.imp.CustomerServiceImp" />
    <!-- 配置切面 -->
    <bean id="myAspectAnno" class="com.dchart.aop.service.aspect.CustomerServiceAspect" />

</beans>

运行结果:

源码:https://gitee.com/kszsa/dchart

 参考地址:http://www.cnblogs.com/wang-meng/p/5641687.html

原文地址:https://www.cnblogs.com/dyh004/p/9376263.html