目录
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的使用。
a:安全和不想掰扯别人的代码,为什么我会这么说呢?首先有的项目其实已经完成了或者代码在别人的模块。你自己不好改动他的部分,但是需要你动手添加后续的需求或者完善他的代码(对对方方法进行增强(advice),而不动到他的代码)。你怕出问题,这时候aop就可以上场,他会帮你解决这个问题。
【jdk8】,【maven3.5】,【intellj idea2018】
org.springframework.boot spring-boot-starter-aop 3.2.2
@SpringBootApplication public class MainRunApplication { public static void main(String args[]){ new SpringApplication(MainRunApplication.class).run(); } }
@Before(方法前置处理),@After(方法后置处理),@Around(方法环绕处理),@AfterReturning(方法返回值处理),@AfterThrowing(异常后续处理)
a:编撰被切入的类,并添加匹配@Before规则的方法
@Component public class MainTest { public Mapbefore(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监听方法的参数"); } }
a:编撰被切入的类,并添加匹配@After规则的方法
@Component public class MainTest { public Mapbefore(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(Mapoutput){ 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监听方法的参数"); Mapafter = mainTest.after(new HashMap<>()); System.out.println("@After修改了传进来的参数,后续长度为"+after.size()); } }
a:编撰被切入的类,并添加匹配@AfterReturning规则的方法
@Component public class MainTest { public Mapbefore(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, Mapoutput){ 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监听方法的参数"); Mapafter = mainTest.after(new HashMap<>()); System.out.println("@After修改了传进来的参数,后续长度为"+after.size()); Map afterReturn = mainTest.afterReturn(new HashMap<>()); } }
a:新建个注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RoutingWith { String value() default "master"; }
b:编撰被切入的类,并添加匹配@Around规则的方法,以及使用注解RoutingWith
@Component public class MainTest { public Mapbefore(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, Mapoutput){ 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监听方法的参数"); Mapafter = mainTest.after(new HashMap<>()); System.out.println("@After修改了传进来的参数,后续长度为"+after.size()); Map afterReturn = mainTest.afterReturn(new HashMap<>()); mainTest.around(); } }
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)里面的点。
https://download.csdn.net/download/weixin_36667844/88783992