https://blog.csdn.net/qq_26525215/article/details/52400791
使用场景:
日志、鉴权等一些和业务无关且重复的功能
几个基本概念:
切点:需要增加功能的位置(可以通过注解或者pointCut方法)
切面:需要增加的功能的代码(通过定义一个xxAcept类,选择性的添加方法,为切点在不同位置【代码段的前中后】增加功能)
织入:Spring和其它纯Java AOP框架一样,在运行时完成织入
通知:通知有各种类型,其中包括“around”、“before”和“after”等通知
动态代理实现AOP(JDKProxy):
通过动态代理的方式实现AOP,动态代理生成的这个对象,在具体的方法上,新增了切面中定义的功能,使得我们在不改变原对象的基础上新增了我们需要的功能。
代理会生成一个类,这个类继承这个接口,并且代理要切面的类,在实现具体的方法时,实际上是调用了原来类的方法,只是在调用前和调用后做了一些事情而已。
这种方式只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,可以通过CGLib创建动态代理。
AOP失效的情景,为什么会失效?
https://blog.csdn.net/u012373815/article/details/77345655
1.在对象内部的方法中调用该对象的其他使用aop机制的方法,被调用方法的aop注解失效。
原因:
正常aop的顺序是这样的:一个类作为被代理对象,动态的生成一个代理对象,在这个新的代理对象中的invoke()方法里会执行一些额外新增的功能和被代理对象的某个方法,而这个方法是通过调用被代理对象的这个方法而实现的。当使用注解增加一个aop切点时,实际上是把这个类作为了一个被代理对象,因此在执行一个被调用的方法时,这个aop会失效。
2.private方法不生效
private方法一定是这个类的某个方法去调用的,本质和上一种情况是一样的,因此aop失效。
初识aop的一个demo:
MyAspect.java
package com.test.aoptest.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.util.Arrays; /** * @author gaoyuan * @date 2019/7/15 11:27 */ @Aspect @Component public class MyAspect { private Logger logger = LoggerFactory.getLogger(getClass()); @Pointcut("execution(public * com.test.aoptest.service.*.*(..))") public void pointCut(){ } @Before("pointCut()") public void before(JoinPoint joinPoint) throws Throwable { // 接收到请求,记录请求内容 logger.info("【注解:Before】------------------切面 before"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); // 记录下请求内容 logger.info("【注解:Before】执行的业务方法名=CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); logger.info("【注解:Before】业务方法获得的参数=ARGS : " + Arrays.toString(joinPoint.getArgs())); } @AfterReturning(returning = "ret", pointcut = "pointCut()") public void afterReturning(Object ret) throws Throwable { // 处理完请求,返回内容 logger.info("【注解:AfterReturning】这个会在切面最后的最后打印,方法的返回值 : " + ret); } @AfterThrowing("pointCut()") public void afterThrowing(JoinPoint jp){ logger.info("【注解:AfterThrowing】方法异常时执行....."); } @After("pointCut()") public void after(JoinPoint jp){ logger.info("【注解:After】方法最后执行....."); } @Around("pointCut()") public Object around(ProceedingJoinPoint pjp) { logger.info("【注解:Around . 环绕前】方法环绕start....."); try { //如果不执行这句,会不执行切面的Before方法及controller的业务方法 Object o = pjp.proceed(); logger.info("【注解:Around. 环绕后】方法环绕proceed,结果是 :" + o); return o; } catch (Throwable e) { e.printStackTrace(); return null; } } }
AopConfiguration.java
package com.test.aoptest.configuration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * @author gaoyuan * @date 2019/7/15 11:39 */ @Configuration @ComponentScan("com.test.aoptest.aspect") @EnableAspectJAutoProxy public class AopConfiguration { }
HelloController.java
package com.test.aoptest.controller; import com.test.aoptest.service.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author gaoyuan (yuangao@rd.netease.com) * @date 2019/7/15 11:43 */ @RestController @RequestMapping("/") public class HelloController { @Autowired private HelloService helloService; @RequestMapping("hello") public String hello() { return helloService.sayHello(); } }
HelloService.java
package com.test.aoptest.service; /** * @author gaoyuan * @date 2019/7/15 11:23 */ public interface HelloService { String sayHello(); void printHello(); int addUser(String name, String pass); }
HelloServiceImpl.java
package com.test.aoptest.service.impl; import com.test.aoptest.service.HelloService; import org.springframework.stereotype.Service; /** * @author gaoyuan * @date 2019/7/15 11:23 */ @Service public class HelloServiceImpl implements HelloService { @Override public String sayHello() { return "hello"; } @Override public void printHello() { System.out.println("hello"); } @Override public int addUser(String name , String pass) { System.out.println("执行Hello组件的addUser添加用户:" + name); if(name.length() < 3 || name.length() > 10) { throw new IllegalArgumentException("name参数的长度必须大于3,小于10!"); } return 20; } }
AoptestApplication.java
package com.test.aoptest; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy(proxyTargetClass = true) @EnableConfigurationProperties public class AoptestApplication { public static void main(String[] args) { SpringApplication.run(AoptestApplication.class, args); } }
application.properties
server.port=8080
spring.profiles.active=dev
application-dev.properties
这个文件其实撒都没有,做作了一下 啊哈哈哈