spring-aop的介绍和使用

目录

1:为什么我会使用这个框架

2:那怎么快速入手属于自己的spring-aop呢(或者说怎么在自己项目调用spring-aop这个框架呢)

1->环境(自己去建一个maven项目)

2->导入spring-aop框架包(pom.xml)

3->编撰项目启动类(spring-boot)

4->spring-aop主要的五个注解

5->spring-aop之@Before

6->spring-aop之@After

7->spring-aop之@AfterReturning

8->spring-aop之@Around

3:敲黑板

4:下一篇动态代理和静态代理

5:本章资源下载链接


先说说这篇文章看完你能学习到什么吧

1:你可以知道为什么我会用这个,2:你能从中学习到aop的使用。
1:为什么我会使用这个框架

a:安全和不想掰扯别人的代码,为什么我会这么说呢?首先有的项目其实已经完成了或者代码在别人的模块。你自己不好改动他的部分,但是需要你动手添加后续的需求或者完善他的代码(对对方方法进行增强(advice),而不动到他的代码)。你怕出问题,这时候aop就可以上场,他会帮你解决这个问题。

2:那怎么快速入手属于自己的spring-aop呢(或者说怎么在自己项目调用spring-aop这个框架呢)
1->环境(自己去建一个maven项目)
【jdk8】,【maven3.5】,【intellj idea2018】
2->导入spring-aop框架包(pom.xml)

    
        org.springframework.boot
        spring-boot-starter-aop
        3.2.2
    
3->编撰项目启动类(spring-boot)
@SpringBootApplication
public class MainRunApplication {

    public static void main(String args[]){
        new SpringApplication(MainRunApplication.class).run();
    }
}
4->spring-aop主要的五个注解
@Before(方法前置处理),@After(方法后置处理),@Around(方法环绕处理),@AfterReturning(方法返回值处理),@AfterThrowing(异常后续处理)
5->spring-aop之@Before

a:编撰被切入的类,并添加匹配@Before规则的方法

@Component
public class MainTest {

    public Map before(String input){
        System.out.println("这是匹配到aop@Before切面规则的方法");
        return null;
    }
}

b:编写切面类Aspect并添加@Before注解的方法

@Aspect
@Component
public class RoutingAspect {

    @Before(value = "execution(* *..before(String))")
    public void aopBefore(JoinPoint joinPoint){
        System.out.println(joinPoint.getArgs()[0]);
    }

}

c:编写启动测试

@SpringBootApplication
public class MainRunApplication {

    public static void main(String args[]){
        ConfigurableApplicationContext run = new SpringApplication(MainRunApplication.class).run();
        MainTest mainTest = run.getBeanFactory().getBean("mainTest",MainTest.class);
        mainTest.before("这是前置@Before监听方法的参数");
    }
}
6->spring-aop之@After

a:编撰被切入的类,并添加匹配@After规则的方法

@Component
public class MainTest {

    public Map before(String input){
        System.out.println("这是匹配到aop@Before切面规则的方法");
        return null;
    }

    public Map after(Map output){
        System.out.println("这是匹配到aop@After切面规则的方法");
        return output;
    }
}

b:编写切面类Aspect并添加@After注解的方法

@Aspect
@Component
public class RoutingAspect {

    @Before(value = "execution(* *..before(String))")
    public void aopBefore(JoinPoint joinPoint){
        System.out.println(joinPoint.getArgs()[0]);
    }

    @After(value = "execution(* *..after(java.util.Map)) && args(output)",argNames = "output")
    public void aopBefore(Map output){
        System.out.println("修改了传进来的参数,原始长度为"+output.size());
        output.put(1,1);
    }

}

c:编写启动测试

@SpringBootApplication
public class MainRunApplication {

    public static void main(String args[]){
        ConfigurableApplicationContext run = new SpringApplication(MainRunApplication.class).run();
        MainTest mainTest = run.getBeanFactory().getBean("mainTest",MainTest.class);
        mainTest.before("这是前置@Before监听方法的参数");
        Map after = mainTest.after(new HashMap<>());
        System.out.println("@After修改了传进来的参数,后续长度为"+after.size());
    }
}

7->spring-aop之@AfterReturning

a:编撰被切入的类,并添加匹配@AfterReturning规则的方法

@Component
public class MainTest {

    public Map before(String input){
        System.out.println("这是匹配到aop@Before切面规则的方法");
        return null;
    }

    public Map after(Map output){
        System.out.println("这是匹配到aop@After切面规则的方法");
        return output;
    }

    public Map afterReturn(Map output){
        System.out.println("这是匹配到aop@AfterReturn切面规则的方法");
        return output;
    }
}

b:编写切面类Aspect并添加@AfterReturning注解的方法

@Aspect
@Component
public class RoutingAspect {


    @AfterReturning(value = "execution(* *..afterReturn(java.util.Map))",returning = "output")
    public void aopAfterReturning(JoinPoint joinPoint, Map output){
        output.put(1,3);
        System.out.println("@AfterReturning修改了返回值" + output.size());
    }

    @Before(value = "execution(* *..before(String))")
    public void aopBefore(JoinPoint joinPoint){
        System.out.println(joinPoint.getArgs()[0]);
    }

    @After(value = "execution(* *..after(java.util.Map)) && args(output)",argNames = "output")
    public void aopBefore(Map output){
        System.out.println("修改了传进来的参数,原始长度为"+output.size());
        output.put(1,1);
    }

}

c:编写启动测试

@SpringBootApplication
public class MainRunApplication {

    public static void main(String args[]){
        ConfigurableApplicationContext run = new SpringApplication(MainRunApplication.class).run();
        MainTest mainTest = run.getBeanFactory().getBean("mainTest",MainTest.class);
        mainTest.before("这是前置@Before监听方法的参数");
        Map after = mainTest.after(new HashMap<>());
        System.out.println("@After修改了传进来的参数,后续长度为"+after.size());
        Map afterReturn = mainTest.afterReturn(new HashMap<>());
    }
}
8->spring-aop之@Around

a:新建个注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RoutingWith {
    String value() default "master";
}

b:编撰被切入的类,并添加匹配@Around规则的方法,以及使用注解RoutingWith

@Component
public class MainTest {

    public Map before(String input){
        System.out.println("这是匹配到aop@Before切面规则的方法");
        return null;
    }

    public Map after(Map output){
        System.out.println("这是匹配到aop@After切面规则的方法");
        return output;
    }

    public Map afterReturn(Map output){
        System.out.println("这是匹配到aop@AfterReturn切面规则的方法");
        return output;
    }

    @RoutingWith(value = "mama")
    public void around(){
        System.out.println("这是匹配到aop@Around切面规则的方法");
    }
    
}

c:编写切面类Aspect并添加@Around注解的方法,匹配切面方法上有RoutingWith注解的方法

@Aspect
@Component
public class RoutingAspect {

    @Around("@annotation(routingWith)")
    public Object routingWithDataSource(ProceedingJoinPoint proceedingJoinPoint, RoutingWith routingWith) throws Throwable{
        String key = routingWith.value();
        System.out.println(key);
        return proceedingJoinPoint.proceed();
    }

    @AfterReturning(value = "execution(* *..afterReturn(java.util.Map))",returning = "output")
    public void aopAfterReturning(JoinPoint joinPoint, Map output){
        output.put(1,3);
        System.out.println("@AfterReturning修改了返回值" + output.size());
    }

    @Before(value = "execution(* *..before(String))")
    public void aopBefore(JoinPoint joinPoint){
        System.out.println(joinPoint.getArgs()[0]);
    }

    @After(value = "execution(* *..after(java.util.Map)) && args(output)",argNames = "output")
    public void aopBefore(Map output){
        System.out.println("修改了传进来的参数,原始长度为"+output.size());
        output.put(1,1);
    }

}

d:编写启动测试

@SpringBootApplication
public class MainRunApplication {

    public static void main(String args[]){
        ConfigurableApplicationContext run = new SpringApplication(MainRunApplication.class).run();
        MainTest mainTest = run.getBeanFactory().getBean("mainTest",MainTest.class);
        mainTest.before("这是前置@Before监听方法的参数");
        Map after = mainTest.after(new HashMap<>());
        System.out.println("@After修改了传进来的参数,后续长度为"+after.size());
        Map afterReturn = mainTest.afterReturn(new HashMap<>());
        mainTest.around();
    }
}

3:敲黑板

1:为什么第一步为什么要再pom.xmlj加入那个包?

答:因为想要使用spring-aop,必须先导入他的框架包,才能使用

2:为什么导入的是spring-boot-starter-aop

答:因为导入这个可以直接使用spring-boot,而不需要重复再导入spring-boot的包,这里说下spring-boot-starter这个合集开头是啥意思--------spring boot本来就是可以开箱即用的全家桶框架集合,他们通过约定俗成的方式介入到spring boot,并把自己命名成spring-boot-starter这样子开头的名,开发者只要导入相关的spring-boot-starter的就可以用他们的框架,例如spring-boot-starter-aop,这里有aspectj的包,也有spring-aop,也有spring-boot-starter,这样我们只要导入一个这样的包就可以使用spring boot的模块

3:spring-boot项目启动类的@SpringBootApplication是有啥用

答:这个标明了这个类是spring-boot 的入口启动类,并且里面有集成EnableAutoConfiguration,ComponentScan,Configuration等注解,方便好用,而且想要使用spring-boot启动,只要再加个

public static void main(String args[]){
    new SpringApplication(MainRunApplication.class).run();
}

就可以用了

4:以下代码是获取一个bean为mainTest的方法吗,那我用@Autowired也可以注入吧

ConfigurableApplicationContext run = new SpringApplication(MainRunApplication.class).run();
MainTest mainTest = run.getBeanFactory().getBean("mainTest",MainTest.class);

答:没错的,这个方法相当于@Autowired注入,只是这个是手动获取bean的IOC容器,也就是我们说的控制反转容器,这个容器管理了一大堆扫描到的bean,并在需要的时候(使用@Bean或者@Component等自动注入)

5:@Before(方法前置处理),@After(方法后置处理),@Around(方法环绕处理),@AfterReturning(方法返回值处理),@AfterThrowing(异常后续处理)这四个方法啥意思

答:简单来说就说在对象调用被切面的方法之前,之后,以及方法前后(环绕)进行相应的切面处理,环绕比较简单,就是可以自由处理方法,决定方法要不要调用,以及传参的处理,返回值的处理,AfterReturning是对返回值的处理,Around这个还可以对有相应注解的方法进行切片处理。这种一般用在ORM和日志等需要开启事务等开关上有用到。

6:spring-aop是aop,相对于oop?

答:没错,我们熟悉的oop是面向对象编程,aop就是面向切面编程,也就是Aspect

7:Around环绕可以对方法上有特定注解的方法进行切面,这个方法好像在spring中很好用也常见?

答:没错,我们orm框架中,那些@Service,@Dao相应的都有对应Around切面处理。

8:@After(value = "execution这个execution是接受切面的表达式吗?

答:没错的,execution里面写的是切面的表达式,表示需要匹配的方法规则,例如

execution(* *..after(java.util.Map)) && args(output)表示的是返回类型任意,包名任意类名任意,方法名字为after,参数类型为Map的方法会被当下注解规则匹配到切面。这里重点说下第一个*表示方法返回类型,第二个星号表示包名任意,然后..(两个点)表示零次或者多次点,也就是包名例如(com.zzu.z)里面的点。

4:下一篇动态代理和静态代理
5:本章资源下载链接

https://download.csdn.net/download/weixin_36667844/88783992

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