JavaSE阶段配置文件解析、反射以及注解综合小练习

JavaSE阶段配置文件解析、反射以及注解综合小练习

练习要求

先创建一个项目wzry,在项目中创建一个resource源文件夹,在该文件夹下,有一个
web.properties配置文件。该配置文件内容如下:
package=cn #package是key,值是cn指的是包
annotantion=HeroType #HeroType是值,是一个英雄类型注解

请解析这个配置文件,然后将package作为扫描【遍历硬盘上cn目录下的所有文件夹、文件】的目录包,
扫描包下所有java类,将所有HeroType注解的值是"力量型"英雄的类,调用beGoodAt()方法。

通过分析题意,我们将本题分为三个部分
1.解析配置文件,获得包名及注解名
2.获得注解类对应的字节码文件
3.通过反射找出符合题意的类,并调用方法

首先在main方法中解析properties类型的配置文件
此处采用的是类加载器的方式,通过当前类的加载器获取
另外也可以通过当前线程获取,方法很多,不再赘述了

public class HeroTest2 {
	public static Class hero = null;
	public static void main(String[] args) throws Exception {
		// 解析配置文件,获得包名和注解名
		Properties p = new Properties();
		ClassLoader classLoader = HeroTest2.class.getClassLoader();//获取当前类加载器
		String pa = null;// 声明包名
		String ann = null;// 声明注解名
		try(
			/*
			 * 	2. 通过类加载器的方式 
	 				1.同当前类的加载器获取
		 			1.当前类.class.getClassLoader();// 获取当前类加载器
		 			2.classLoader.getResourceAsStream("文件路径/文件名");//通过类加载器获取流对象,如果是源文件夹,直接文件名
			 */
			InputStream is = classLoader.getResourceAsStream("web.properties");//获取当前类加载器并获取流
			BufferedInputStream bis = new BufferedInputStream(is);
		){
			p.load(bis);// load方法解析配置文件
			pa = p.getProperty("package");// 获得包名cn
			ann = p.getProperty("annotantion");// 获取注解名HeroType
		} catch (FileNotFoundException e) {
			System.out.println("文件没有找到异常!");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("IO异常!");
			e.printStackTrace();
		}
		// 获得项目的绝对路径
		File file = new File(pa);
		String paPath = file.getAbsolutePath();
//		System.out.println(paPath);
		//E:\Java_software\eclipse-jee-neon-2\eclipse_workspace\wzry\cn
		String path = paPath.substring(0, (paPath.length()-pa.length()-1));
//		System.out.println(path);
		//E:\Java_software\eclipse-jee-neon-2\eclipse_workspace\wzry
		File dir = new File(path);
		getHero(dir,pa,ann);//调用获取注解对象字节码文件方法
		getStrengthHero(dir,pa);//调用获取对象方法
	}

获取到配置文件中的包名及注解名之后,便可以实现对对应的包进行遍历,查找符合题意的java文件
其中获取注解类字节码文件的代码如下:

	public static Class getHero(File dir,String pa,String ann) throws Exception {
		if (dir.isFile()  &&  dir.getName().equals(ann + ".java")  &&  dir.getAbsolutePath().contains(pa)) {
			String path = dir.getAbsolutePath();
//			System.out.println(path);
//			// E:\Java_software\eclipse-jee-neon-2\eclipse_workspace\wzry\src\cn\itsource\hero\HeroType.java
			path = path.substring(path.indexOf(pa));
//			System.out.println(path);
//			// cn\itsource\hero\HeroType.java
			path = path.replace("\\",".").replaceAll(".java", "");
//			System.err.println(path);
//			// cn.itsource.hero.HeroType
			hero = Class.forName(path);
		} else if (dir.isDirectory()) {
			File[] listFiles = dir.listFiles();
			for (File file : listFiles) {
				getHero(file,pa,ann);
			}
		}
		return null;
	}

通过递归方法遍历文件夹,找到符合配置文件中注解名的类并获取到其字节码文件。
接下来只剩通过class.getAnnotation()方法获取到每个java文件的注解内容,再将其与题目中的所需类型进行比对即可。

	public static void getStrengthHero(File dir,String pa) throws Exception {
		if (dir.isFile()  &&  dir.getName().endsWith(".java")  && !dir.getName().contains("HeroType") && dir.getAbsolutePath().contains(pa)) {
			String path = dir.getAbsolutePath();
//			System.out.println(path);
			path = path.substring(path.indexOf(pa)).replace("\\",".").replaceAll(".java", "");
//			System.err.println(path);
			// 通过文件名获取每一个对应的字节码对象
			Class c = Class.forName(path);
			if (c.getAnnotation(hero) != null) {
				String annString = c.getAnnotation(hero).toString();
//				System.out.println(annString);
				/*
				 * @cn.itsource.hero.HeroType(type=智力型)
				   @cn.itsource.hero.HeroType(type=敏捷型)
				   @cn.itsource.hero.HeroType(type=力量型)
				 */
				if (annString.contains("力量型")) {
					// 通过当前匹配上的字节码对象去获取对象中的普通方法 beGoodAt()
					Method method = c.getMethod("beGoodAt");
					// 执行非static修饰的beGoodAt()方法, 是通过当前method对象调用执行方法 invoke()
					// Object invoke(Object obj, Object... args) //非static需要对象
					// 3.先通过字节码对象获取一个构造方法对象,再去用newInstance()创建对象
					method.invoke(c.getConstructor().newInstance());
				}
			}
		} else if (dir.isDirectory()) {
			File[] listFiles = dir.listFiles();
			for (File file : listFiles) {
				getStrengthHero(file,pa);
			}
		}
	}

通过反射的方式获取类中的方法、构造方法,并创建对象调用方法即可完成题目要求。

附上题目已给的几个已知类:
Hero类

/**
 * 英雄类
 *	抽象基类
 */
public abstract class Hero {
	/**
	 * 擅长的能力
	 */
	public abstract void beGoodAt();
}

注解类

/**
 *	英雄类型
 */
@Target(ElementType.TYPE)//只有一个值,且属性的名字是value可以省略
@Retention(RetentionPolicy.RUNTIME)
public @interface HeroType {
	String type();
}

@HeroType(type="智力型")
public class Master extends Hero {

	@Override
	public void beGoodAt() {
		System.out.println("烧死你.....");
	}

}
@HeroType(type="敏捷型")
public class Shooter extends Hero {

	@Override
	public void beGoodAt() {
		System.out.println("射你.....");
	}

}
@HeroType(type="力量型")
public class Warrior extends Hero {

	@Override
	public void beGoodAt() {
		System.out.println("砍死你.....");
	}

}

以上即为JavaSE初学阶段关于注解、反射以及配置文件解析的综合小练习,仅供参考。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值