zoukankan      html  css  js  c++  java
  • Spring AOP简述

    使用面想对象(Object-Oriented Programming,OOP)包含一些弊端,当需要为多个不具有继承关系的对象引入公共行为时,例如日志,安全检测等。我们只有在每个对象中引入公共行为,这样程序中就产生了大量的代码,程序就不便于维护了,所以就有了一个面向对象编程的补充---面向切面编程(Aspect-Oriented Programming, AOP),AOP关注的方向是横向的,OOP关注的时纵向的;OOP中模块的基本单元是class,而AOP中基本的模块单元称作Aspect。

    AOP的其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能。像日志记录,事务处理,权限控制等功能,都可以用AOP来“优雅”地实现,使这些额外功能和真正的业务逻辑分离开来,软件的结构将更加清晰。AOP是OOP的一个强有力的补充。

    Key Terms

    学习AOP,我们需要关注一些技术名词:

    1. Aspect: 切面,横向贯穿于多个类的某个服务,比如事务处理
    2. Join Point:又叫point cut,是指那些方法需要被执行"AOP"
    3. Advice:join point上特定的时刻执行的操作,Advice有几种不同类型,下文将会讨论(通俗地来讲就是起作用的内容和时间点)。
    4. Introduction: 给对象增加方法或者属性
    5. Target object: Advice起作用的对象
    6. AOP proxy:为实现AOP所实现的代理,在Spring中实现代理的方式有两种,JDK代理和CGLIB代理
    7. Weaving:将Advice织入join point的过程

    Advice的类型:

    1. Before advice: 在执行join point之前执行
    2. After returning advice: 执行在join point这个方法返回之后的advice
    3. After throwing advice: 当方法抛出异常之后执行
    4. After (finally) advice: Advice在方法退出之后执行。
    5. Around advice: 包围一个连接点的通知,如方法调用。这是最 强大的通知。Aroud通知在方法调用前后完成自定义的行为。它们负责选择继续执行连接点或通过 返回它们自己的返回值或抛出异常来短路执行。

    Spring AOP的使用

    有三种方式使用Spring AOP,分别是:@Aspect-based(Annotation),Schema-based(XML),以及底层的Spring AOP API。其中@Aspect-based是使用最多的一种方式。我们所讲的例子也是基于@Aspect-based(Annotation)这种方式的

    Aspect based

    配置

    Spring AOP Maven依赖

    <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>4.2.1.RELEASE</version>
    </dependency>   
    
    <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aop</artifactId>
         <version>4.2.1.RELEASE</version>
    </dependency>
    
    <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjrt</artifactId>
         <version>1.6.11</version>
    </dependency>  
    
    <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.8.7</version>
    </dependency>
    

    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-3.1.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
       <!-- 使能AOP-->
       <aop:aspectj-autoproxy/>
    
       <!-- 声明一个切面-->
       <bean id="myAspect" class="com.mj.spring.aop.MyAspect"></bean>
       <!--声明AOP target-->
       <bean id="userManager" class="com.mj.spring.aop.UserManager"></bean>
    </beans>
    

    编码

    定义切面类

    <!--定义切面类-->
    @Aspect 
    public class MyAspect {
    
    //定义切点, 这个切点的使用范围是: 定义在com.mj.spring.aop包下的所有方法
    @Pointcut("execution(* com.mj.spring.aop.*.*(..))")
    public void aPointcut() {
    }
    
    //定义Before Advice
    @Before("aPointcut()")
    public void beforeAdvice() {
        System.out.println("before advice is executed!");
    }
    
    //定义AfterReturning Advice
    @AfterReturning(pointcut = "aPointcut()", returning = "r")
    public void afterReturningAdvice(String r) {
        if (r != null)
            System.out.println("after returning advice is executed! returning String is : " + r);
    }
    
    //定义After Advice
    @After("aPointcut()")
    public void AfterAdvice() {
        System.out.println("after advice is executed!");
    }
    
    @After("aPointcut() && args(str)")
    public void AfterAdviceWithArg(String str) {
        System.out.println("after advice with arg is executed!arg is : " + str);
    }
    
    //定义afterThrowingAdvice Advice
    @AfterThrowing(pointcut = "aPointcut()", throwing = "e")
    public void afterThrowingAdvice(Exception e) {
        System.out.println("after throwing advice is executed!exception msg is : " + e.getMessage());
    }
    
    //定义around advice
    @Around(value="execution(public String com.mj.spring.aop.UserManager.getUser(..))")
    public void aroundSayHello(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("Around Before !! ");
        joinPoint.proceed();
        System.out.println("Around After !! ");
    }
    
    }
    

    定义AOP target类

    public class UserManager {
    /*这个方法需要一个参数*/
    public void addUser(String user) {
        System.out.println("addUser(String str) method is executed!");
    }
    
    public void deleteUser() {
        System.out.println("deleteUser() method is executed!");
    }
    
    /*这个方法返回一个字符串*/
    public String getUser() {
        System.out.println("getUser() method is executed!");
        return "Hello";
    }
    
    /*这个方法抛出一个异常*/
    public void editUser() throws Exception {
        throw new Exception("something is wrong.");
    }
    }
    

    测试类

    public class UserManagerTest {
    
    private ApplicationContext applicationContext=null;
    @Before
    public void setUp() throws Exception {
        applicationContext=new ClassPathXmlApplicationContext("ApplicationContext.xml");
    }
    
    @Test
    public void shoud_get_user_maneger_bean() throws Exception {
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        assertThat(userManager!=null,is(true));
    }
    @Test
    public void should_apply_before_advice_and_after_advice_and_after_advice_with_arg() throws Exception{
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        userManager.addUser("Jun.Ma");
    }
    @Test
    public void should_apply_before_advice_and_after_advice() throws Exception{
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        userManager.deleteUser();
    }
    
    @Test
    public void should_apply_before_advice_and_after_advice_and_after_throwing_advice() throws Exception{
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        userManager.editUser();
    }
    
    @Test
    public void should_apply_before_advice_and_after_advice_after_return_advice() throws Exception{
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        userManager.getUser();
    }
    @Test
    public void should_apply_around_advice_and_before_advice_and_after_advice_after_return_advice() throws Exception{
        UserManager userManager = (UserManager) applicationContext.getBean("userManager");
        userManager.getUser();
    }
    }
    

    Reference

    http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-enable-aspectj-java Spring Document Reference

    http://blog.psjay.com/posts/summary-of-spring-3-aop/ Spring AOP 3 Summary

    源码git路径: git@github.com:jma19/spring.git

    欢迎转载
  • 相关阅读:
    【iBoard电子学堂开发板例程】【12个 stm32 例程发布】
    【iCore双核心组合是开发板例程】【12个 verilog 中级实验例程发布】
    【新产品发布】【iHMI43 智能液晶模块 2013 版】
    【新产品发布】【EVC8001 磁耦隔离式 USB 转 RS-485】
    【iHMI43真彩液晶模块】发布新版 DEMO 软件包,版本号为 0.14
    【新产品发布】【iCore2 ARM / FPGA 双核心板】
    急性淋巴瘤化疗术后高热不退案
    产后便秘案
    药疹治案
    胃癌化疗后急救案
  • 原文地址:https://www.cnblogs.com/jun-ma/p/4833539.html
Copyright © 2011-2022 走看看