很多框架都用到了注解,常见的如spring,hibernate,springMvc,SpringBoot等。使用注解有什么用呢?
注解和xml一样,都能提供元数据的支持,二者都有各自的好吃,但是使用注解会和代码的结合性更密切一些,我认为注解提供元数据的支持,在接口拦截器和AOP等编程方式能很好的在业务中对需求的实现!
注解的知识点可以参考此篇博主的文章:
https://www.cnblogs.com/huajiezh/p/5263849.html
http://www.importnew.com/10294.html
javaEE项目中对项目业务具有横向切割的有2项技术:1.拦截器 2.AOP面向切面变成,后面分别来讲他们是如何与注解一起结合工作的。
一、拦截器与java注解的结合
struts2的拦截和springmvc的拦截原理差不多,在此以springMvc的拦截器为例子:
注解类:
package cn.xdf.dtmanager.system.interceptop; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import java.lang.annotation.*; /** * Created by fengch on 2018/1/9. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit { /** * 次数,默认最大 * @return */ int count() default Integer.MAX_VALUE; /** * 时长,单位毫秒 * @return */ long time() default 6000; }
springMvc拦截器的配置:
<mvc:interceptors> <mvc:interceptor> <!-- 统计接口时长拦截器 --> <mvc:mapping path="/**" /> <bean class="cn.xdf.dtmanager.system.interceptop.InterceptorTimeCount" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.xdf.dtmanager.system.interceptop.InterceptorTest" /> </mvc:interceptor> </mvc:interceptors>
package cn.xdf.dtmanager.system.interceptop; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.annotation.Annotation; /** * 计算接口访问时长问题 * Created by fengch on 2017/11/3. */ public class InterceptorTest extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { RequestLimit requestLimit = findAnnotation((HandlerMethod) handler, RequestLimit.class); if(requestLimit != null) { System.out.println(requestLimit.count() + "::::::::" + requestLimit.time()); } else { System.out.println("此Action方法上面有没注解!"); return true; } } return super.preHandle(request, response, handler); } private <T extends Annotation> T findAnnotation(HandlerMethod handler, Class<T> annotationType) { T annotation = handler.getBeanType().getAnnotation(annotationType); if (annotation != null) return annotation; return handler.getMethodAnnotation(annotationType); } }
此findAnnotation方法已经封装好了注解类型的获取。通过传入的注解类进行判断是否为null,否则并上是使用了注解。在来看看实际使用注解的Controller:
@ResponseBody @RequestMapping(value = "/test.do") @RequestLimit(count = 10, time = 5000L) public String test(HttpServletRequest request, HttpServletResponse response) { try { Boolean b = masterTeacherService.queryMasterTeacherClassRoom("73", "aaaccc", "test"); System.out.println(b); } catch (Exception e) { e.printStackTrace(); } System.out.println("aaaaaaaaaaaaaaaaaa"); return "aaaaaa" + DateUtil.dateToString(new Date(), DateUtil.DATATIME_FORMMATER); }
二、AOP和java注解的结合
AOP可以分为配置文件的方式和注解的方式,由于使用注解是特定的业务进行注解切面拦截,所以后面是以注解的方式配置AOP生效。
spring的配置文件开启AOP注解如下:
<!-- 启动AspectJ支持 --> <aop:aspectj-autoproxy />注解类:
package cn.xdf.dtmanager.system.interceptop; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import java.lang.annotation.*; /** * Created by fengch on 2018/1/9. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit { /** * 次数,默认最大 * @return */ int count() default Integer.MAX_VALUE; /** * 时长,单位毫秒 * @return */ long time() default 6000; }
AOP类:
package cn.xdf.dtmanager.system.service.impl; import cn.xdf.dtmanager.system.interceptop.RequestLimit; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** * Created by fengch on 2018/1/9. */ @Component @Aspect public class AopAspectTest { @Before("execution(* cn.xdf.dtmanager.business.*.service.*.query*(..)) && @annotation(requestLimit)") public void aroundAdvice(JoinPoint joinPoint, RequestLimit requestLimit) { System.out.println(requestLimit); System.out.println("test````````````````````````"); } }
注意拦截的是类跟注解同时存在的会被AOP所拦截。