Spring AOP的两种实现方式(AspectJ注解配置和方法配置)

AspectJ是一个java实现的AOP框架,它能够对java代码进行AOP编译(一般在编译期进行),让java代码具有AspectJ的AOP功能(当然需要特殊的编译器),可以这样说AspectJ是目前实现AOP框架中最成熟,功能最丰富的语言,更幸运的是,AspectJ与java程序完全兼容,几乎是无缝关联,因此对于有java编程基础的工程师,上手和使用都非常容易。

Spring AOP 与ApectJ 的目的一致,都是为了统一处理横切业务,但与AspectJ不同的是,Spring AOP 并不尝试提供完整的AOP功能(即使它完全可以实现),Spring AOP 更注重的是与Spring IOC容器的结合,并结合该优势来解决横切业务的问题,因此在AOP的功能完善方面,相对来说AspectJ具有更大的优势,同时,Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。在AspectJ 1.5后,引入@Aspect形式的注解风格的开发,Spring也非常快地跟进了这种方式,因此Spring 2.0后便使用了与AspectJ一样的注解。请注意,Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器。

下面是Spring AOP的AspectJ注解式实现:

自定义注解

package com.dust.exercises.aop;

import java.lang.annotation.*;

/**
 * Created by zhaohongyang on 2018/8/14.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
    String customName();
}

 

定义一个被拦截的方法(注解式拦截)

package com.dust.exercises.aop;

import org.springframework.stereotype.Service;

/**
 * Created by zhaohongyang on 2018/8/14.
 */
@Service
public class DemoAnnotationService {

    //自定义注解中的自定义方法
    @Action(customName="注解拦截的add操作")
    public void add(){

    }
}

定义一个被拦截的方法(方法式拦截)

package com.dust.exercises.aop;

import org.springframework.stereotype.Service;

/**
 * Created by zhaohongyang on 2018/8/14.
 */
@Service
public class DemoMethodService {

    public void add(){

    }
}

 

定义切面的类

package com.dust.exercises.aop;

import org.aspectj.lang.JoinPoint;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created by zhaohongyang on 2018/8/14.
 */
@Aspect
@Component
public class LogAspect {

    @Pointcut("@annotation(com.dust.exercises.aop.Action)")
    public void annotationPointCut() {
    }

    @After("annotationPointCut()")
    public void after(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Action action = method.getAnnotation(Action.class);
        System.out.println("注解式拦截," + action.customName());
    }

    @Before("execution(* com.dust.exercises.aop.DemoMethodService.*(..))")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("方法规则式拦截," + method.getName());
    }

}

配置类,使用@EnableAspectJAutoProxy 注解开启Spring 对AspectJ 代理的支持。

package com.dust.exercises.aop;

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

/**
 * Created by zhaohongyang on 2018/8/14.
 */
@Configuration
@ComponentScan("com.dust.exercises.aop")
@EnableAspectJAutoProxy
public class AopConfig {
}

运行

package com.dust.exercises.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Created by zhaohongyang on 2018/8/14.
 */
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
        DemoMethodService demoMethodService = annotationConfigApplicationContext.getBean(DemoMethodService.class);
        DemoAnnotationService demoAnnotationService = annotationConfigApplicationContext.getBean(DemoAnnotationService.class);
        demoMethodService.add();
        demoAnnotationService.add();
        annotationConfigApplicationContext.close();
    }
}

结果

 

posted @ 2018-08-15 20:20  尘埃代码  阅读(398)  评论(0编辑  收藏  举报