跳至主要內容

反射

chanchaw大约 1 分钟languagejava

反射

根据方法名称调用方法

package test;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Test {
 
	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		stu.setAge(1);
		stu.setName("lin");
		
		//1.无参
		Method method = stu.getClass().getMethod("getName");
		String name = (String) method.invoke(stu);
		
		//2.一个参数,后面的 Class.forName("java.lang.String") 表示参数是字符串类型
		Method method2 = stu.getClass().getMethod("setName",Class.forName("java.lang.String"));
		method2.invoke(stu, "meng");
		
		//3.多参
		Method method3 = stu.getClass().getMethod("method1",int.class,Class.forName("java.lang.String"));//后两个参数获得的都是class对象
		method3.invoke(stu,15, "zhang");
	}
}

判断类使用了指定的注解

if(clazz.isAnnotationPresent(ComponentScan.class)){
    //TODO: 当某类实现了某个接口时要执行的逻辑
}

判断对象实现某接口

if(obj instanceof ComponentScan){
    //TODO: xxx
}

遍历源码文件

其实是遍历编译后的 class 文件在手写 spring (项目 summer - https://gitee.com/chanchaw/summer.git)时写了遍历项目文件的注解 ComponentScan ,根据设置的包路径扫描并创建 bean 容器,关键代码如下:

// 类 configClass 使用了注解 @ComponentScan(自定义模拟 spring 的)
if(configClass.isAnnotationPresent(ComponentScan.class)){
    ComponentScan annotation = (ComponentScan)configClass.getAnnotation(ComponentScan.class);
    String beanPackage = annotation.value();// 拿到包路径:com.chanchaw.service
    System.out.println("配置类设置了包路径:" + beanPackage);

    // 包路径转换为文件夹路径
    // com.chanchaw.service = com/chanchaw/service
    String path = beanPackage.replace(".","/");

    // 通过 ClassLoader 获取文件 - 编译后的
    ClassLoader classLoader = SummerApplicationContext.class.getClassLoader();
    URL resource = classLoader.getResource(path);

    // 遍历指定目录下的所有文件
    File file = new File(resource.getFile());
    if(file.isDirectory())
        for (File f : file.listFiles()) {
            // 编译后 class 文件的完整路径:D:\software\summer\target\classes\com\chanchaw\service\OrderService.class
            String absolutePath = f.getAbsolutePath();
            // 将上面的文件完整路径转换为包路径+类名称:com.chanchaw.service.OrderService
            String packageAndClass = getPackagePath(absolutePath);
            try {
                Class<?> clazz = classLoader.loadClass(packageAndClass);
                // 使用了注解 @Component,并且没有设置 @Scope("prototype")
                // 则在容器中创建实例对象
                if(clazz.isAnnotationPresent(Component.class)){
                    BeanDefinition beanDefinition = getBeanDefinition(clazz);
                    beanDefinitionMap.put(beanDefinition.getDefaultBeanName(),beanDefinition);
                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }

        }
}