注解看起来是一个很神奇的东西,也是一个解耦的利器。直入正题,从创建一个自定义的注解开始。
1.创建注解@MyLogger,添加属性message,fallback。这里Target对象选择方法,Retention选择运行时。Ctrl+点击可以查看ElementType的可选值,里面有非常详尽的注释,这里不再赘述。
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLogger {
String message() default "";
String fallback() default "fallbackMethod";
}
2.创建切面MyLoggerAspectj,里面做一个增强处理,如果message为add,返回结果为原方法+fallback设定的方法。
@Aspect
@Component
public class MyLoggerAspectj {
Logger logger = LoggerFactory.getLogger(MyLoggerAspectj.class);
private String PROCESS_TYPE_ADD = "add";
@Around("@annotation(myLogger)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, MyLogger myLogger) throws Throwable {
Object o1 = proceedingJoinPoint.proceed();
if (PROCESS_TYPE_ADD.equals(myLogger.message())) {
//走fallback
String methodName = myLogger.fallback();
try {
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Class[] types = signature.getParameterTypes();
Method method = proceedingJoinPoint.getTarget().getClass().getMethod(methodName, types);
try {
Object o2 = method.invoke(proceedingJoinPoint.getTarget(), proceedingJoinPoint.getArgs());
ArrayList list = new ArrayList();
if (o1 instanceof List) {
list.addAll((ArrayList) o1);
}
list.add(o2);
return list;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
return o1;
}
}
3.在Service层添加新接口及方法。
@MyLogger(message = "add", fallback = "createUser")
@Override
public List<User> getAno(Integer id) {
List list = new ArrayList();
list.add(userMapper.getUserById(id));
return list;
}
public User createUser(Integer id) {
User user = new User();
user.setId(-1);
user.setUserName("系统自动创建用户");
user.setStatus(-1);
return user;
}
4.Controller层添加方法。
@RequestMapping("/ano")
public List<User> ano(Integer id) throws Throwable {
return userService.getAno(id);
}
5.访问urlhttp://localhost:8080/ano?id=1。确认结果包含自动创建用户。
通过以上几个步骤,很轻松可以创建一个自定义的注解。完整工程:https://github.com/showsys20/spring-demo-cm.git。
以上过程,实际上是常规开发时的一个模式,从下往上实装,dao->service->controller。
这里只是演示了一个简单的应用,实际上可以用类似的方式,在切面里加上guava包的RateLimiter或者Redis来实现流量控制,服务降级等功能。
版权声明:本文为u012129340原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。