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); }}