• 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

  • 相关阅读:
    WebForms 开发基础
    Web 开发基础
    Winform MDI窗体容器、权限、简单通讯
    Winform TextBox中只能输入数字的几种常用方法(C#)
    WinForm TreeView递归加载
    窗体四边阴影
    winform 进程,线程
    树状数组 / 二维树状数组
    zkw线段树
    [HNOI2014]世界树
  • 原文地址:https://www.cnblogs.com/dyh004/p/9376263.html
Copyright © 2020-2023  润新知