springboot注解简单使用aop

AOP的概念

Aspect:切面,指的是横切多个类的一种模块。在Spring中,切面用的就是普通的类(xml或者带@Aspect注解配置):

Joint point: 连接点,表示要横切的方法。

Advice:建议,一个切面在特定的连接点执行的方法。建议有::等

PointCut:切入点,能匹配上连接点的那些方法,Advice和切点表达式有关,它会在任何匹配的连接点执行。Spring使用AspectJ的切入点表达式来表示连接点

Introduction:引入,声明额外的方法或者属性,比如让bean实现一个接口

Target Object: 指已经被一个或者多个切面建议过的对象

Aop proxy:Aop代理,采用JDK代理或者CGLIB代理

Weaving:织入,织入切面的过程,可以在编译,加载,或者运行时进行织入,对于Spring AOP来说,是在运行时起作用的。

Advice的种类:

Before advice :连接点运行之前运行

After returning advice:连接点正常运行之后进行,比如一个方法正常return并且没有抛出异常

After throwing advice:抛出异常之后运行

After(finally) advice:不论是连接点是正常结束还是抛异常结束都会执行

Aroud advice:在方法调用之前和之后运行,是一个非常强大的advice,能够自定义方法的行为

添加aspectjweaver依赖

SpringBoot的AOP是默认开启的,不需要加注解@EnableAspectJAutoProxy


		<dependency>
			<groupId>org.aspectjgroupId>
			<artifactId>aspectjweaverartifactId>
			<version>1.9.6version>
		dependency>

定义切面和切入点@Aspect表示该类是一个切面

package com.example.springboot.config;

import com.example.springboot.aspect.Demo;
import javafx.beans.property.Property;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
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.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.PropertyValue;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.AnnotatedElement;

/**
 * 定义切面
 */
@Aspect
@Component
public class DemoAspect {

    //定义一个切入点@annotation定义在方法上
    @Pointcut("@annotation(com.example.springboot.aspect.Demo)"
            +"||@within(com.example.springboot.aspect.Demo)")//@within定义类注解的切入点
    public void PinCut(){
    }
    //定义切点二
    @Pointcut("within(com.example.springboot.service..*)")
    public void PinCut2(){

    }

    @Around("PinCut()")
    public Object Aroud(ProceedingJoinPoint point) throws Throwable {
        
        MethodSignature signature = (MethodSignature) point.getSignature();
        Demo demo;
        //获取方法上的注解
        demo = AnnotationUtils.findAnnotation(signature.getMethod(), Demo.class);
        if (demo==null){
            //注解在类上时调用该方法
            demo=AnnotationUtils.findAnnotation(signature.getDeclaringType(),Demo.class);
        }
        Object[] args = point.getArgs();
       //BeanWapper bean的包装器 可以进行bean的数据绑定
        BeanWrapper wrapper = new BeanWrapperImpl(args[0]);
        //使用时需要先判断该bean是否有该属性
       if (wrapper.isWritableProperty("pwd")){
           wrapper.setPropertyValue(new PropertyValue("pwd","123456"));
       }
       if (wrapper.isWritableProperty("name")){
           wrapper.setPropertyValue("name","小明");
       }
        System.out.println(demo.value());
        System.out.println("环绕通知");
        return point.proceed();
    }

    @Before("PinCut2()")
    public void befor(){
        System.out.println("方法执行前通知");
    }


}

切入点标识符

execution: 匹配连接点
//表示service包下的所有方法
execution(* com.example.springboot.service.*.*(..))
within: 某个类里面
//表示service包以及子包下的所有方法  单独针对mapper不生效
@Pointcut("within(com.example.springboot.service..*)")
this: 指定AOP代理类的类型
//this(com.xyz.service.AccountService):代理实现了AccountService接口
target:指定目标对象的类型
//target(com.xyz.service.AccountService):目标对象实现了AccoutService接口
args: 指定参数的类型
//args(java.io.Serializable):表示传递的参数是Serializable
bean:指定特定的bean名称,可以使用通配符(Spring自带的)
//bean(tradeService):bean的名字,可以使用通配符
@target: 带有指定注解的类型
//@target(org.springframework.transaction.annotation.Transactional):目标对象有@Transactional注解
@args: 指定运行时传的参数带有指定的注解
//@args(com.xyz.security.Classified):有一个参数,并且传递的类型有@Classfied注解
@within: 匹配使用指定注解的类
//	作用在类上
@annotation:指定方法所应用的注解
 //	作用在方法上
切入点表达式可以用&&,||,!来组合使用
 @Pointcut("@annotation(com.example.springboot.aspect.Demo)"
            +"||@within(com.example.springboot.aspect.Demo)")

定义一个注解

package com.example.springboot.aspect;

import java.lang.annotation.*;

/**
 * 定义Demo注解
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Demo {

    public String value() default "first";

}

package com.example.springboot.utils;

import com.example.springboot.aspect.Demo;
import com.example.springboot.mapper.UserBaseInfoMapper;
import com.example.springboot.pojo.UserBaseInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class AspectDemo {
    @Demo(value = "second")
    public void test(UserBaseInfo userBaseInfo){
        System.out.println("改方法执行了");
        System.out.println(userBaseInfo);
    }
}
UserBaseInfo{id=8, name='大力', username='15526054511', pwd='123456', status='1'}
second
环绕通知
改方法执行了
UserBaseInfo{id=8, name='小明', username='15526054511', pwd='666666', status='1'}

你可能感兴趣的:(spring,boot,spring,java)