1.aop
术语
1.连接点: 那些方法可以增强,这些方法就是
2.切入点: 实际增强的方法,就是切入点
3.通知(增强): 增强写的逻辑就是
前置通知
后置通知
环绕通知
异常通知
最终通知
4.切面: 是动作 把通知应用到切入点过程
2.aop操作
1.spring基于AspectJ实现AOP
(1)基于xml
(2)基于注解
2.引入依赖aspectj
3.切入点表达式
execution([权限修饰][返回类型][类的全路径]方法名称)
注解实现
//创建被增强类
@Component
public class User {
public void add(){
System.out.println("我是add方法...");
}
}
//创建增强类
//增强类
@Component
@Aspect
public class UserProxy {
@Before("execution(* com.aopdemo.User.add(..))")
public void before(){
System.out.println("方法前......");
}
}
//配置类或者配置xml
@Configuration
@ComponentScan(basePackages = {"com.aopdemo"})
@EnableAspectJAutoProxy
public class ConfigAop {
}
//测试类
public class Test {
@org.junit.Test
public void test1(){
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);
User user = context.getBean("user",User.class);
user.add();
}
}
对相同切入点抽取
@Pointcut
增强优先级
如果一个类有俩个以上的增强类
在增强类上加@Order(1) 数值越小优先级越高
自定义注解
谈下这两个: @Retention 和 @Target
@Retention :用来说明该注解类的生命周期。它有以下三个参数:
RetentionPolicy.SOURCE : 注解只保留在源文件中
RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃
RetentionPolicy.RUNTIME : 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。
@Target : 用来说明该注解可以被声明在那些元素之前。
ElementType.TYPE:说明该注解只能被声明在一个类前。
ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
ElementType.PACKAGE:说明该注解只能声明在一个包名前。
秒杀接口限流 自定义注解
这里推荐使用google提供的guava工具包中的RateLimiter进行实现,其内部是基于令牌桶算法进行限流计算
1)添加依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
2)自定义限流注解
@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {}
3)自定义切面类
@Component
@Scope
@Aspect
public class AccessLimitAop {
@Autowired
private HttpServletResponse httpServletResponse;
private RateLimiter rateLimiter = RateLimiter.create(20.0);
@Pointcut("@annotation(com.changgou.webSecKill.aspect.AccessLimit)")
public void limit(){}
@Around("limit()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
boolean flag = rateLimiter.tryAcquire();
Object obj = null;
try{
if (flag){
obj=proceedingJoinPoint.proceed();
}else{
String errorMessage = JSON.toJSONString(new Result(false,StatusCode.ERROR,"fail"));
outMessage(httpServletResponse,errorMessage);
}
}catch (Throwable throwable) {
throwable.printStackTrace();
}
return obj;
}
private void outMessage(HttpServletResponse response, String errorMessage) {
ServletOutputStream outputStream = null;
try {
response.setContentType("application/json;charset=UTF-8");
outputStream = response.getOutputStream();
outputStream.write(errorMessage.getBytes("UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4)使用自定义限流注解