愚公系列2022年01月 Java教学课程 77-注解的多种方式

网友投稿 682 2022-05-30

一、注解

1.概述

概述

对我们的程序进行标注和解释

注解和注释的区别

注释: 给程序员看的

注解: 给编译器看的

使用注解进行配置配置的优势

代码更加简洁,方便

2.自定义注解

格式

public @interface 注解名称 { public 属性类型 属性名() default 默认值 ; }

属性类型

基本数据类型

String

Class

注解

枚举

以上类型的一维数组

代码演示

public @interface Anno2 { } public enum Season { SPRING,SUMMER,AUTUMN,WINTER; } public @interface Anno1 { //定义一个基本类型的属性 int a () default 23; //定义一个String类型的属性 public String name() default "itheima"; //定义一个Class类型的属性 public Class clazz() default Anno2.class; //定义一个注解类型的属性 public Anno2 anno() default @Anno2; //定义一个枚举类型的属性 public Season season() default Season.SPRING; //以上类型的一维数组 //int数组 public int[] arr() default {1,2,3,4,5}; //枚举数组 public Season[] seasons() default {Season.SPRING,Season.SUMMER}; //value。后期我们在使用注解的时候,如果我们只需要给注解的value属性赋值。 //那么value就可以省略 public String value(); } //在使用注解的时候如果注解里面的属性没有指定默认值。 //那么我们就需要手动给出注解属性的设置值。 //@Anno1(name = "itheima") @Anno1("abc") public class AnnoDemo { }

注意

如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可

自定义注解案例

需求

自定义一个注解@Test,用于指定类的方法上,如果某一个类的方法上使用了该注解,就执行该方法

实现步骤

自定义一个注解Test,并在类中的某几个方法上加上注解

在测试类中,获取注解所在的类的Class对象

获取类中所有的方法对象

遍历每一个方法对象,判断是否有对应的注解

代码实现

//表示Test这个注解的存活时间 @Retention(value = RetentionPolicy.RUNTIME) public @interface Test { } public class UseTest { //没有使用Test注解 public void show(){ System.out.println("UseTest....show...."); } //使用Test注解 @Test public void method(){ System.out.println("UseTest....method...."); } //没有使用Test注解 @Test public void function(){ System.out.println("UseTest....function...."); } } public class AnnoDemo { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException { //1.通过反射获取UseTest类的字节码文件对象 Class clazz = Class.forName("com.itheima.myanno3.UseTest"); //创建对象 UseTest useTest = (UseTest) clazz.newInstance(); //2.通过反射获取这个类里面所有的方法对象 Method[] methods = clazz.getDeclaredMethods(); //3.遍历数组,得到每一个方法对象 for (Method method : methods) { //method依次表示每一个方法对象。 //isAnnotationPresent(Class annotationClass) //判断当前方法上是否有指定的注解。 //参数:注解的字节码文件对象 //返回值:布尔结果。 true 存在 false 不存在 if(method.isAnnotationPresent(Test.class)){ method.invoke(useTest); } } } }

3.元注解

概述

元注解就是描述注解的注解

元注解介绍

示例代码

@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD}) //指定注解使用的位置(成员变量,类,方法) @Retention(RetentionPolicy.RUNTIME) //指定该注解的存活时间 //@Inherited //指定该注解可以被继承 public @interface Anno { } @Anno public class Person { } public class Student extends Person { public void show(){ System.out.println("student.......show.........."); } } public class StudentDemo { public static void main(String[] args) throws ClassNotFoundException { //获取到Student类的字节码文件对象 Class clazz = Class.forName("com.itheima.myanno4.Student"); //获取注解。 boolean result = clazz.isAnnotationPresent(Anno.class); System.out.println(result); } }

4.改写服务器

需求

目前项目中Servlet和url对应关系,是配置在xml文件中的,将其改为在Servlet类上通过注解配置实现

实现步骤

定义一个注解(@WebServlet),注解内有一个属性urlPatterns

在servlet类上去使用该注解,来指定当前Servlet的访问路径

创建一个注解解析类(AnnoParseServletConfig),该类实现ParseServletConfig接口

实现parse方法

【愚公系列】2022年01月 Java教学课程 77-注解的多种方式

代码实现

@Target(ElementType.TYPE) //指定该注解可以使用在类上 @Retention(RetentionPolicy.RUNTIME)//指定该注解的存活时间 --- 为运行期 public @interface WebServlet { //让用户去指定某一个Servlet在进行访问的时候所对应的请求uri public String urlPatterns(); } // 这里只给出了LoginServlet的配置,其他Servlet同理 @WebServlet(urlPatterns = "/servlet/loginservlet") public class LoginServlet implements HttpServlet{ @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) { //处理 System.out.println("LoginServlet处理了登录请求"); //响应 httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("登录成功"); } } public class AnnoParseServletConfig implements ParseServletConfig { //定义一个servlet路径所对应的常量 public static final String SERVLET_PATH = "http-dynamic-server\\src\\com\\itheima\\myservlet"; //定义包名 public static final String SERVLET_PACKAGE_NAME = "com.itheima.myservlet."; @Override public void parse() { //获取类名 // 1.获得servlet所在文件夹的路径,并封装成File对象 File file = new File(SERVLET_PATH); // 2.调用listFiles方法,获取文件夹下所有的File对象 File[] servletFiles = file.listFiles(); // 3.遍历数组,获取每一个File对象 for (File servletFile : servletFiles) { // 4.获取File对象的名字(后缀名) String servletFileName = servletFile.getName().replace(".java", ""); // 5.根据包名 + 类名 得到每一个类的全类名 String servletFullName = SERVLET_PACKAGE_NAME + servletFileName; try { // 6.通过全类名获取字节码文件对象 Class servletClazz = Class.forName(servletFullName); // 7.判断该类是否有WebServlet注解 if(servletClazz.isAnnotationPresent(WebServlet.class)){ // 8.判断该Servlet类是否实现HttpServlet接口 //获取该类所实现的所有的接口信息,得到的是一个数组 Class[] interfaces = servletClazz.getInterfaces(); //定义一个boolean类型的变量 boolean flag = false; //遍历数组 for (Class clazzInfo : interfaces) { //判断当前所遍历的接口的字节码对象是否和HttpServlet的字节码文件对象相同 if(clazzInfo == HttpServlet.class){ //如果相同,就需要更改flag值.结束循环 flag = true; break; } } if(flag){ // 9.如果满足,则获取注解中的urlPattrens的值, WebServlet annotation = (WebServlet) servletClazz.getAnnotation(WebServlet.class); String uri = annotation.urlPatterns(); // 10.创建当前Servlet类对象存入值位置 HttpServlet httpServlet = (HttpServlet) servletClazz.newInstance(); // 11.存入集合的键位置 ServletConcurrentHashMap.map.put(uri,httpServlet); // }else{ // 12.如果不满足,抛出异常 //false就表示当前的类还没有实现HttpServlet接口 throw new NotImplementsHttpServletException(servletClazz.getName() + "Not Implements HttpServlet"); } } } catch (NotImplementsHttpServletException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } } public class LoaderResourceRunnable implements Runnable { @Override public void run() { // //执行parse方法 // ParseServletConfig parseServletConfig = new PropertiesParseServletConfig(); // parseServletConfig.parse(); // ParseServletConfig parseServletConfig = new XMLParseServletConfig(); // parseServletConfig.parse(); ParseServletConfig parseServletConfig = new AnnoParseServletConfig(); parseServletConfig.parse(); } }

5G教育 Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:读书笔记:《图解HTTP》第一章、第二章
下一篇:少年的肩,应担起草长莺飞,和清風明月【我们都是华为云专家】
相关文章