spring注解之AOP

spring注解之AOP

        AOP,spring重要特性之一,基于OOP思想,面向切面编程,可以在不破坏原代码的情况下动态的在其前后增加功能,功能与装饰者模式相似.spring在@Transanction事务和@Cacheable数据缓存都用此拦截.我们经常用其去打日志和加事务等.

        要想使用注解的方式使用AOP,需要了解以下注解:

        @Aspect 声明是一个切面
        @After,@Before,@Around 定义建言(advice),可直接将拦截规则(切点)作为参数
        @AfterReturning 在目标方法返回后调用
        @AfterThrowing 在目标方法抛出异常后调用
        @Pointcut 定义拦截规则

        JoinPoint 连接点(当然,这个不是注解)

        以下,我用两种方式使用spring的aop

        注解式

        自定义注解类:

package com.yczuoxin.demo.aop;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cutpoint {
    String name();
}

        被注解式切的类:

package com.yczuoxin.demo.aop;

import org.springframework.stereotype.Service;

@Service
public class AnnotationDemo {
    @Cutpoint(name = "注解式切面...")
    public void doSomething(){
        System.out.println("AnnotationDemo doSomething method");
    }
}

 该注解是方便找到切点.

       被方法规则切的类

package com.yczuoxin.demo.aop;

import org.springframework.stereotype.Service;

@Service
public class MethodDemo {

    public void doSomething(){
        System.out.println("MethodDemo doSomething method");
    }
}

        切面类

package com.yczuoxin.demo.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;

@Aspect
@Component
public class AspectDemo {
    @Pointcut("@annotation(com.yczuoxin.demo.aop.Cutpoint)")
    public void annotationCutPoint(){}

    @Before("annotationCutPoint()")
    public void before(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Cutpoint cutpoint = method.getAnnotation(Cutpoint.class);
        System.out.println("注解式切面" + cutpoint.name());
    }

    @After("execution(* com.yczuoxin.demo.aop.MethodDemo.*(..))")
    public void after(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("方法规则切面" + method.getName());
    }
}

 @Pointcut的方法名是声明切点的名字,下面的建言(例如@Before)里面传入该方法的名字即代表使用的该切点.而下面@After注解的方法规则.第一个”*”表示任意返回类型(例如public),第二个”*”表示在com.yczuoxin.demo.aop.MethodDemo类下所有的方法,且(..)“表示这个方法的入参为任意类型、数量.

       切面配置类

package com.yczuoxin.demo.aop;

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

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.yczuoxin.demo.aop")
public class AopConfig {
}

 @EnableAspectAutoProxy:使用AspectJ方式自动代理注解.默认是不开启的

       测试类

package com.yczuoxin.demo.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
        AnnotationDemo annotationDemo = context.getBean(AnnotationDemo.class);
        MethodDemo methodDemo = context.getBean(MethodDemo.class);
        // 调用被注解切的方法
        annotationDemo.doSomething();
        // 调用被方法规则切的方法
        methodDemo.doSomething();
    }
}

注解式切面注解式切面...
AnnotationDemo doSomething method
MethodDemo doSomething method
方法规则切面doSomething
        看结果便知道,我们的方法切入成功了.spring的AOP主要是用了代理模式,因为可以看出来,aop可以自动选择是JDK自带的代理模式还是CGlib.我们知道代理模式可以在不修改原代码的情况下,增强方法或者切入方法.所以aop是spring的重要特点之一.

猜你喜欢

转载自blog.csdn.net/ycxzuoxin/article/details/80876125