JAVA注解
元注解
1、标注注解的注解,叫做元注解。@Target注解用来修饰@Component可以出现的位置。
@Target(ElementType[] value())// 说明属性名称是value
以下表示@Component注解可以出现在类上、属性上。
@Target(value = {ElementType.TYPE, ElementType.FIELD})
2、使用某个注解的时候,如果注解的属性名是value的话,value可以省略。如果注解的属性值是数组,并且数组中只有一个元素,大括号可以省略。
3、@Retention 也是一个元注解。用来标注@Component注解最终保留在class文件当中,并且可以被反射机制读取。(RetentionPolicy.RUNTIME) retention:保持
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
//表示注解可以出现在类上()。元注解--修饰Component注解的注解
public @interface Component {String value;}
//@Component(属性名 = 属性值, 属性名 = 属性值, 属性名 = 属性值....)
//@Component(value = "userBean")
// 如果属性名是value,value可以省略。
@Component("userBean")
public class User {
// 编译器报错,不能出现在这里。
//@Component(value = "test")
//private String name;
}
模拟spring注解式开发中的包扫描机制
目前只知道一个包的名字,扫描这个包下所有的类,当这个类上有@Component注解的时候,实例化该对象,然后放到Map集合中。
public class ComponentScan {
public static void main(String[] args){
Map<String,Object> beanMap = new HashMap<>();
// 目前只知道一个包的名字,扫描这个包下所有的类,当这个类上有@Component注解的时候,实例化该对象,然后放到Map集合中。
String packageName = "com.powernode.bean";
// 开始写扫描程序。
// . 这个正则表达式代表任意字符。这里的"."必须是一个普通的"."字符。不能是正则表达式中的"."
// 在正则表达式当中怎么表示一个普通的"."字符呢?使用 \. 正则表达式代表一个普通的 . 字符。
String packagePath = packageName.replaceAll("\\.", "/");
//System.out.println(packagePath);
// com是在类的根路径下的一个目录。
URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
String path = url.getPath();//这样就拿到了绝对路径
//System.out.println(path);
// 获取一个绝对路径下的所有文件
File file = new File(path);
File[] files = file.listFiles();
Arrays.stream(files).forEach(f -> {
try {
//System.out.println(f.getName());//文件类名 如:Order.class
//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);
}
}
Spring注解原码
@Service原码:(其他几个Component、Repository、Controller 等差不多)
@Target({ElementType.TYPE}) //这个注解只运行出现在类上
@Retention(RetentionPolicy.RUNTIME)//该注解最终保留在class文件当中,并且可以被反射机制读取。
@Documented
@Component
public @interface Service {
@AliasFor(//Component是老大,其他几个都是Component的别名
annotation = Component.class
)
String value() default "";
}