注解的本质和使用:

​ JAVA中的注解都是继承了Annotation接口的一个接口

​ JAVA语言规范定义了注解的定义使用@interface

元注解:

注解的注解,且只能作用于注解上的注解
@Target [取值ElementType枚举]

​ 定义注解要使用的元素

    /** 类、接口(包括注释类型)或enum声明*/
    TYPE,

    /** 字段声明(包括enum常量) */
    FIELD,

    /** 方法 */
    METHOD,

    /** 参数 */
    PARAMETER,

    /** 构造器 */
    CONSTRUCTOR,

    /** 局部变量 */
    LOCAL_VARIABLE,

    /** 作用于注解的 */
    ANNOTATION_TYPE,

    /** 包 */
    PACKAGE,

    /**
     * 
     *类型参数声明
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 使用类型
     *
     * @since 1.8
     */
    TYPE_USE
@Retention [取值RetentionPolicy]

​ 定义注解的保留策略 Source(源码级别) CLASS(字节码级别) RUNTIME(运行期间)

@Documented

​ 标记使用的注解是否包含在生成的用户文档中(加了可以生成在文档中)

@Indexed

​ 注解是否具有继承的特性(继承的子类将拥有此注解)

自定义实现注解:

​ 模拟@Component 和 @Bean 注解实现IOC

/**
 * Created by 于占峰 on 2020/3/27/027.
 */
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoBeanAnnotation {
    String value() default "";
}

@Target(value = {ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoComponentAnnotation {
    String value() default "";
}

@DemoComponentAnnotation
public class DemoBeanA {

    public DemoBeanA() {
        System.out.println("DemoBeanA构造器初始化");
    }

    @DemoBeanAnnotation("DemoBeanB")
    public static DemoBeanB cerateB(){
        System.out.println("调用cerateB实例化实体类B....");
        return new DemoBeanB();
    }
    @DemoBeanAnnotation("DemoBeanC")
    public DemoBeanC cerateC(){
        System.out.println("调用cerateC实例化实体类c....");
        return new DemoBeanC();
    }
}

public class DemoBeanB {
}

public class DemoBeanC {
}

public class IOCContainer {
    //用于装入实体类的map容器
    private static HashMap container = new HashMap();

    //装入
    public  static void putBean(String key,Object value){
        //如果已经存在则不再装入
        //if(container.containsKey(key)) return;
        container.put(key,value);
    }
    //取出
    public static Object getBean(String key){
        return container.get(key);
    }
}



/**
 * Created by 于占峰 on 2020/3/28/028.
 */
public class Main {
    //声明用于装入类路径的set集合
   private static HashSet<String> classPathSet = new HashSet<>();

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        getClassPath("com.yzf.demo.demo.annotation");
        //遍历类名集合
        for (String className:classPathSet) {
            Class<?> clazz = Class.forName(className);
            //判断类是否存在DemoComponentAnnotation注解
            if(clazz.isAnnotationPresent(DemoComponentAnnotation.class))
                //实例化并装入IOC容器
                IOCContainer.putBean(className,clazz.newInstance());
            //获得类的方法列表
            Method[] methods = clazz.getDeclaredMethods();
            //遍历
            for(Method method:methods){
                //判断method是否存在DemoBean注解
                if(method.isAnnotationPresent(DemoBeanAnnotation.class)){
                    //获得方法的DemoBeanAnnotation注解的value
                    String beanName = method.getAnnotation(DemoBeanAnnotation.class).value();
                    //判断是否为静态工厂 如果是静态工厂则直接调用方法初始化对象 而不用考虑形参和对象
                    if(Modifier.isStatic(method.getModifiers())){
                        IOCContainer.putBean(beanName,method.invoke(null));
                    }else{
                        //如果是实例工厂 从容器中取出实例对象 并再次实例化后装入
                        IOCContainer.putBean(beanName,method.invoke(IOCContainer.getBean(className)));
                    }
                }
            }
        }
    }


   private static void getClassPath(String packageStr){
        //获得本地路径
       URL url = Main.class.getResource("/" + packageStr.replaceAll("\\.", "/"));
       //得到文件对象
       File classDir = new File(url.getFile());
       //遍历
       for (File file:classDir.listFiles()) {
           if (file.isDirectory()){
               //如果是文件夹则继续向下递归
               getClassPath(packageStr + "." + file.getName());
           }else {
               //判断文件是否为.class结尾的文件 如果不是能跳入下一次循环
               if(!file.getName().endsWith(".class")) continue;
               //替换掉.class后缀 拼接为类的包路径名
               String clazzName = (packageStr + "." + file.getName().replace(".class",""));
               //装入集合
               classPathSet.add(clazzName);
           }
       }
    };
}




DemoBeanA构造器初始化
调用cerateC实例化实体类c....
调用cerateB实例化实体类B....
总结:

本次只是对注解进行了粗浅的学习,了解了一些基本参数和逻辑,深入使用有待继续探索.