java----注解
Annotation:
注解:
作用1:当对程序做解释的时候和注释的意义差不多
作用2:可以在编译期读取注解中的信息然后为程序所利用。
注释作用1
public class Test{ //可以起到一个提示的作用 @Override public String toString() { return super.toString(); } }
系统自带注解
public class Demo{ public static void main(String[] args) { Test test = new Test(); test.test(); //使用了不推荐使用的方法 } } //忽略编译期不当的警告 @SuppressWarnings("all") class Test{ //表示这个方法不再建议使用; @Deprecated public void test(){ System.out.println("方法已经过时"); } //检查此方法是不是覆盖了父类的方法 @Override public String toString() { return super.toString(); } }
前言:注解的解析完全依赖于反射。
自定义注解,一个简单的例子
import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; public class Demo{ public static void main(String[] args) throws IllegalAccessException, InstantiationException { Class<Cat> catClass = Cat.class; //获取类中应用的指定的注解 MyAnnotation annotation = catClass.getAnnotation(MyAnnotation.class); //通过反射获取注解中的值 String name = annotation.name(); int age = annotation.age(); String[] like = annotation.like(); Color color = annotation.color(); //实例化对象 Cat cat = catClass.newInstance(); cat.setAge(age); cat.setColor(color); cat.setLike(like); cat.setName(name); System.out.println(cat); } } enum Color{ red,black; } //表示注解再运行时依然存在 @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ public String name(); public int age() default 10; //给变量设置默认值 public String[] like(); //定义一个数组变量 public Color color(); //定义一个枚举变量 } @MyAnnotation(name="bin",like = {"鱼",},color = Color.black) class Cat{ private String name; private String[] like; private Color color; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String[] getLike() { return like; } public void setLike(String[] like) { this.like = like; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + ", like=" + Arrays.toString(like) + ", color=" + color + ", age=" + age + '}'; } }
注解详细解释
注解我们可以定义在类上,成员变量上等等
@TestA //使用了类注解 public class UserAnnotation { @TestA //使用了类成员注解 private Integer age; @TestA //使用了构造方法注解 public UserAnnotation(){ } @TestA //使用了类方法注解 public void a(){ @TestA //使用了局部变量注解 Map m = new HashMap(0); } public void b(@TestA Integer a){ //使用了方法参数注解 } }
四个元注解
@Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括:
ElemenetType.CONSTRUCTOR----------------------------构造器声明
ElemenetType.FIELD --------------------------------------域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE------------------------- 局部变量声明
ElemenetType.METHOD ----------------------------------方法声明
ElemenetType.PACKAGE --------------------------------- 包声明
ElemenetType.PARAMETER ------------------------------参数声明
ElemenetType.TYPE--------------------------------------- 类,接口(包括注解类型)或enum声明
@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括:
RetentionPolicy.SOURCE ---------------------------------注解将被编译器丢弃
RetentionPolicy.CLASS -----------------------------------注解在class文件中可用,但会被JVM丢弃
RetentionPolicy.RUNTIME VM-------将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
@Inherited 允许子类继承父类中的注解。
方法
#判断方法或者类是否有这个注解 xx.isAnnotationPresent(X.class) #isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。 父类.class.isAssignableFrom(子类.class) 子类实例 instanceof 父类类型
示例
import org.junit.Test; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import static java.lang.annotation.ElementType.*; @Target({TYPE, METHOD, FIELD, CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @interface TestA { String name(); int id() default 0; Class gid(); } @TestA(id = 1, name = "type", gid = Long.class) //类注解 class UserAnnotation { @TestA(name = "param", id = 2, gid = Long.class) //类成员注解 private Integer age; @TestA(name = "construct", id = 3, gid = Long.class)//构造方法注解 public UserAnnotation() { } @TestA(name = "public method", id = 4, gid = Long.class) //类方法注解 public void a() { } @TestA(name = "protected method", id = 5, gid = Long.class) //类方法注解 protected void b() { } @TestA(name = "private method", id = 6, gid = Long.class) //类方法注解 private void c() { } public void b(Integer a) { } } public class SpringbootProjectApplicationTests { @Test public void test() throws ClassNotFoundException, NoSuchMethodException { Class<UserAnnotation> userAnnotationClass = UserAnnotation.class; //获取类上注解的信息 Annotation[] annotations = userAnnotationClass.getAnnotations(); for (Annotation annotation : annotations) { TestA testA = (TestA) annotation; //打印了类注解的信息 System.out.println(testA.id() + "--" + testA.name() + "-" + testA.gid()); } //获取所有声明的方法的注解信息(不包含构造方法) Method[] declaredMethods = userAnnotationClass.getDeclaredMethods(); for (Method method:declaredMethods){ boolean annotationPresent = method.isAnnotationPresent(TestA.class); if (annotationPresent){ TestA testA = method.getAnnotation(TestA.class); System.out.println(testA.id() + "--" + testA.name() + "-" + testA.gid()); } } //获取指定的声明的方法的注解信息(不包含构造方法),获取字段的方式和方法类似getDeclareField("xx"); Method b = userAnnotationClass.getDeclaredMethod("b"); System.out.println(b.getAnnotation(TestA.class).id()); //获取所有构造方法的注解信息(指定的构造方法同理) Constructor<?>[] constructors = userAnnotationClass.getConstructors(); for (Constructor constructor:constructors){ boolean annotationPresent = constructor.isAnnotationPresent(TestA.class); if (annotationPresent){ TestA testA = (TestA) constructor.getAnnotation(TestA.class); System.out.println(testA.id() + "--" + testA.name() + "-" + testA.gid()); } } } }
使用注解完成类和表结构的映射关系(ORM)
使用注解进行数据表的创建
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface TestTable{ String value(); } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface TestUser{ public String columnName(); public String type(); public int len(); } @TestTable("table") public class Test{ @TestUser(columnName="id",type = "int",len = 10) private int id; @TestUser(columnName="username",type = "String",len = 32) private String username; @TestUser(columnName="password",type = "String",len = 32) private String password; public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class<?> aClass = Class.forName("com.zy.Test"); Field username = aClass.getDeclaredField("username"); TestUser annotation = username.getAnnotation(TestUser.class); System.out.println("字段:"+annotation.columnName()); System.out.println("属性:"+annotation.type()); System.out.println("长度:"+annotation.len()); //字段:username //属性:String //长度:32 //可以向这样获取所有的数据,拼接sql语句来创建数据表; } }
通过注解进行拦截
1、创建注解
import java.lang.annotation.*; /*** * @Target 注解修饰类型 * @Retention 生命周期 * @Documented注解标记的元素,Javadoc工具会将此注解标记元素的注解信息包含在javadoc中 */ @Target(value = {ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LoginUser { /** * 用户角色及默认值 * @return */ String role() default "admin";
2、重写拦截组件,拦截逻辑
import org.apache.commons.lang3.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @Component public class LoginUserInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory.getLogger(LoginUserInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { //注解在方法上的获取方法 LoginUser loginUserAnnotation = ((HandlerMethod) handler).getMethodAnnotation(LoginUser.class); //注解在类上的获取方法 LoginUser classLoginUserAnnotation = ((HandlerMethod) handler).getMethod().getDeclaringClass().getAnnotation(LoginUser.class); if (ObjectUtils.anyNotNull(loginUserAnnotation, classLoginUserAnnotation)) { HttpSession session = request.getSession(false); //获取注解使用过程中的值 System.out.println("pppppppppppppppppppppppppppppppppppppppppppppp"+loginUserAnnotation.role()); } } return true; } }
3.设置拦截规则
import org.springframework.boot.SpringBootConfiguration; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.*; import javax.annotation.Resource; import java.util.List; @SpringBootConfiguration public class WebMvcConfiguration implements WebMvcConfigurer { @Resource private LoginUserInterceptor loginUserInterceptor; /** * addInterceptor()的顺序需要严格按照程序的执行的顺序 * * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { // "/**" 拦截路径及其子路径 registry.addInterceptor(loginUserInterceptor).addPathPatterns("/**"); // "/*" 不拦截子路径 // registry.addInterceptor(loginUserInterceptor).addPathPatterns("/*"); } @Override public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) { } @Override public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) { } @Override public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) { } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) { } @Override public void addFormatters(FormatterRegistry formatterRegistry) { } @Override public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) { } @Override public void addCorsMappings(CorsRegistry corsRegistry) { } @Override public void addViewControllers(ViewControllerRegistry viewControllerRegistry) { } @Override public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) { } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) { } @Override public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) { } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> list) { } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> list) { } @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) { } @Override public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) { } @Override public Validator getValidator() { return null; } @Override public MessageCodesResolver getMessageCodesResolver() { return null; } }
4.在controller上添加注解
@RequestMapping("/toRegister") @LoginUser(role = "tester") public String toRegister(Model model, HttpServletRequest request) { return "register"; }