1.获取类路径的方式

package com.ydlclass.reflect;

import java.net.URL;

public class Bootstrap {
    public static void main(String[] args) {
        //获取ClassPath,继而可以拿到这个类路径下的所有文件
        URL resource = Thread.currentThread().getContextClassLoader().getResource("com/ydlclass/tree");
        //获取的是上下文类加载器;
        System.out.println(resource.getPath());//返回的方式是unix的表示方式

        //对于classLoader可以加载clas文件,也可以加载其他的文件;比如创建一个a.txt文件放在类路径下面,那么可以直接的找到这个文件;
        //但是如果手动的将此文件移动至其他文件下,那么就无法直接找到,需要补上上面的内容
        

    }
}

2.例如Dog,被Singleton所修饰,

package com.ydlclass.reflect;

import com.ydlclass.reflect.homeworks.annotation.Singleton;

import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Singleton
public class Dog {

    private String name;
    public int age;

    public Dog() {
    }
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void eat(){
        eat(null);
    }

    public void eat(String foodName){
        System.out.println(this.getName() + "正在吃:" + foodName);
    }
}

3.使用FileUtils工具类将制定的文件下的路径名称变为全限定名称的一个数组


import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FileUtils {

    private static List<String> PATH = new ArrayList<>();

    public static List<String> listAllClassName(File file){

        File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isDirectory() || name.contains(".class");
            }
        });
        if (files == null || files.length == 0){
            return null;
        }
        for (File file1 : files) {
            if (file1.isDirectory()){
                listAllClassName(file1);
            } else{
                PATH.add(file1.getAbsolutePath());
            }
        }
        return PATH.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                //获取之前不需要的,需要替换的文件名称
                String unablePath = file.getAbsolutePath();
                return s.replace(unablePath + "\\", "").
                        replace(".class", "").
                        replace("\\",".");
                //如果使用replaceAll,其中需要传入一个正则表达式,替换一个"\"需要使用四个”\“
            }
        }).collect(Collectors.toList());
    }


}

4.注解

package com.ydlclass.reflect.homeworks.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Singleton {

}

5.注解的处理器handler,SingletonHandler

package com.ydlclass.reflect.homeworks.handler;

import com.ydlclass.reflect.homeworks.annotation.Singleton;
import com.ydlclass.reflect.homeworks.context.ApplicationContext;

import java.util.List;

public class SingletonHandler {
    public static void handle(List<String> classNames){
        for (String className : classNames) {
            Class<?> aClass = null;
            try {
                aClass = Class.forName(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            //获取注解,
            Singleton annotation = aClass.getAnnotation(Singleton.class);
            //如果这个类是由@Singleton注解修饰的,就创建一个对象放在内存当中

            if (annotation != null){
                Object instance = null;
                try {
                    instance = aClass.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                ApplicationContext.addSingleton(aClass,instance);
            }
        }

    }
}

6.使用应用的上下文环境处理

package com.ydlclass.reflect.homeworks.context;

import com.ydlclass.reflect.Dog;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ApplicationContext {
    //维护一个上下文环境,环境中存放着需要的环境

    private final static Map<Class<?>,Object> CONTEXT = new ConcurrentHashMap<>(8);

    public static void addSingleton(Class<?> clazz, Object entity){
        ApplicationContext.CONTEXT.put(clazz,entity);

    }

    //把实例对象,从容器中取出来
    public static <T> T getSingleton(Class<T> clazz){
        return (T)ApplicationContext.CONTEXT.get(clazz);//类型转换
    }

}

7.主要的调用

package com.ydlclass.reflect.homeworks;

import com.ydlclass.reflect.Dog;
import com.ydlclass.reflect.homeworks.annotation.Singleton;
import com.ydlclass.reflect.homeworks.context.ApplicationContext;
import com.ydlclass.reflect.homeworks.handler.SingletonHandler;
import com.ydlclass.reflect.homeworks.utils.FileUtils;

import java.io.File;
import java.io.FilenameFilter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Bootstrap {
    //使用静态代码块实现类刚被加载时就创建对象

    static {
        //获取ClassPath,继而可以拿到这个类路径下的所有文件
        final URL resource = Thread.currentThread().getContextClassLoader().getResource("");
        File file = new File(resource.getFile());

        //封装的方法完成路径名称转变为全限定名称
        List<String> classNames = FileUtils.listAllClassName(file);

        //注解解析器处理对应的注解
        SingletonHandler.handle(classNames);
    }
    public static void main(String[] args) {
        //获取一个被Singleton修饰的类的对象
        Dog dog = ApplicationContext.getSingleton(Dog.class);
        System.out.println(dog.getName());



    }
}

8.这样做的好处是:

上述就是spring框架的核心类似,程序一起动类一被加载,程序就保存了Application上下文,从上下文中获取实例对象(工程中有些就没有状态,比如有的类只有成员方法,没有具体的属性;那么这种的类适合使用ApplicationContext的方式获取实例对象);

规定了所有的人使用这个对象时就需要从这里去取得,而不是自己new;避免内存浪费

牺牲启动时间,但是节省了运行时的时间;

以后可以使用类似的方式,可以在创建的对象前加上注释,配合解析器就能完成默认值的赋值;

注解本身不能做太多的工作,但是可以配合反射,指定被某些注解注释的类创建对象等其他的操作;

这种方式指定了以后使用这个类是从容器中间获取,而不是自己去new;