当前位置: 首页 > 图灵资讯 > 技术篇> 回顾注解开发

回顾注解开发

来源:图灵教育
时间:2023-06-09 10:14:05

1.回顾注解

注释的存在主要是为了简化XML的配置。Spring6倡导全注解开发。

让我们回顾一下:

●第一:如何定义注释,如何定义注释中的属性?

●第二:如何使用注释?

●第三:如何通过反射机制读取注释?

如何定义注释,如何定义注释中的属性?

package com.powernode.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(value = {ElementType.TYPE})@Retention(value = RetentionPolicy.RUNTIME)public @interface Component {    String value();}

以上是一个自定义的注释:Component

上述修改的注释包括:Target注释和Retention注释,这两种注释称为元注释。

Target注释用于设置Component注释可以出现的位置,上述代表表示Component注释只能用于类和接口。

Retention注释用于设置Component注释的保持性策略,反射机制可以读取上述代表Component注释。

Stringvalue();是Component注释中的一个属性。属性类型String,属性名为value。

1.1自定义注释699
package com.powernode.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//回顾注释  自定义注解//// 标注注解的注解,叫元注解。@Target注释用于修改@Component可以出现的位置。@Target注释用于修改@Component可以出现的位置。/// 以下表示@Component注释可以出现在类上和属性上。//@Target(value = {ElementType.TYPE, ElementType.FIELD})// 以下是@Component注释的类上////@Target(value = {ElementType.TYPE})// 使用注释时,如果注释的属性名是value,value可以省略。//@Target({ElementType.TYPE})// 使用注释时,如果注释的属性值为数组,且数组中只有一个元素,则可以省略大括号。//@Target({ElementType.TYPE})// 使用注释时,如果注释的属性值为数组,且数组中只有一个元素,则可以省略大括号。@Target(ElementType.TYPE)// @Retention 也是元注解。用于标记@component注释,最终保留在class文件中,并可被反射机制读取。@Retention(RetentionPolicy.RUNTIME)public @interface Component {    // 定义注释属性    // String是属性类型    // value是属性名    String value();    // 其他的属性    // String属性类型    // 属性名是name    //String name();    // 数组属性    // 属性类型为:String[]    // 属性名:names    //String[] names();    //int[] ages();    //int age();}
2.如何使用注释?70
package com.powernode.bean;//使用自定义注释  70import com.powernode.annotation.Component;//@Component(属性名 = 属性值, 属性名 = 属性值, 属性名 = 属性值...)//@Component(value = "userBean")// 假如属性名是value,value可以省略。@Component("userBean")public class User {}

使用简单,语法格式:@注释类型名(属性名=属性值,属性名=属性值,属性名=属性值...)

为什么userbean用双引号包括,因为value属性是string类型,字符串。

另外,如果属性名是value,则在使用时可以省略属性名

2.1如何通过反射机制读取注释?70
package com.powernode.client;import com.powernode.annotation.Component;/** * 通过反射机制读取注释  70 **/public class Reflectanotantiontestt1 {    public static void main(String[] args) throws Exception{        // 如何通过反射机制读取注释        // 获取类        Class<?> aClass = Class.forName("com.powernode.bean.User");        // 判断类上是否有这样的注释        if (aClass.isAnnotationPresent(Component.class)) {            // 获取类别上的注释            Component annotation = aClass.getAnnotation(Component.class);            // 访问注释属性            System.out.println(annotation.value());        }    }}
3.注解组件扫描原理71

假设我们现在只知道包名:com.powernode.bean。至于这个包里有多少个bean,我们不知道。我们不知道哪些bean上有注释,哪些bean上没有注释。如何通过程序自动化来判断。

提示文件路径中没有中文,所以我把代码放在这里

E:\javacourse17目录中的spring6buchong

E:\java\spring6buchong\course17src\main\java\com\powernode\client

ComponentScan

package com.powernode.client;import com.powernode.annotation.Component;import java.io.File;import java.net.URL;import java.util.Arrays;import java.util.HashMap;import java.util.Map;/** * 组件扫描原理的注释  71 **/public class ComponentScan {    public static void main(String[] args){        Map<String,Object> beanMap = new HashMap<>();        // 目前只知道一个包的名字,扫描这个包下的所有类别。当这个类别有@component注释时,将对象实例化,然后放入Map集合中。        String packageName = "com.powernode.bean";        // 开始写扫描程序。        String packageName = "com.powernode.bean";        // 开始写扫描程序。        // . 这种正则表达式代表任何字符。这里的".“一定是普通人”."字符。不能是正则表达式中的“”."        // 如何在正则表达式中表达一个普通的“”."字符呢?使用 \. 正则表达式代表普通表达式 . 字符。        String packagePath = packageName.replaceAll("\\.", "/");        //System.out.println(packagePath);        // com是类根路径下的目录。getsystemclasllasloder系统类加载器        URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);        String path = url.getPath();        //System.out.println(path);        // 在绝对路径下获取所有文件        File file = new File(path);        File[] files = file.listFiles();///在bean目录下获取所有子文件        Arrays.stream(files).forEach(f -> {            try {                //System.out.println(f.getName());                //System.out.println(f.getName().split("\\.")[0]);                String className = packageName + "." + f.getName().split("\\.")[0];                //System.out.println(className);                // 通过反射机制进行分析和解释                Class<?> aClass = Class.forName(className);                // 判断类中是否有此注释                if (aClass.isAnnotationPresent(Component.class)) {                    // 获取注解                    Component annotation = aClass.getAnnotation(Component.class);                    String id = annotation.value();                    // 有这个注释的人必须创建对象                    Object obj = aClass.newInstance();                    beanMap.put(id, obj);                }            } catch (Exception e) {                e.printStackTrace();            }        });        System.out.println(beanMap);    }}

回顾注解开发_java_02