先要从当前类出发找到对应包下的所有类文件,再从这些类中筛选出类上有@MyComponent注解的类;把它们都装入Map中,同时类属性完成@MyValue的赋值操作。
测试类结构:
测试类:myse、mycontor、BigStar、MyAnneTest结构都一致
@MyComponent("BigStar")
public class BigStar{
@MyValue("张三")
private String name;
@Override
public String toString() {
return "BigStar{" +
"name='" + name + '\'' +
'}';
}
}
自定义注解类(MyComponent--扫描类)
@Target({ElementType.TYPE}) // 作用范围:类上
@Retention(RetentionPolicy.RUNTIME) // 运行时候生效
public @interface MyComponent {
String value() default "";
}
数据注入(MyValue)
@Target({ ElementType.FIELD}) // 使用的范围 字段上
@Retention(RetentionPolicy.RUNTIME) // 生效时候 运行时候
public @interface MyValue {
String value() default "";
}
首先处理获得项目的包路径:也是IOC启动方法
在junit4 中编写:
MyIOC()方法
private Map
对路径进行处理:
只需要 “包名.类名字” 即可
DirectoryToClass()方法
// 处理类路径--获得 包名字+类名字
private void DirectoryToClass(String Mypath) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
// 获得类路径
// String myclassPath=myclass.getPath();
List
难点已经解决了,剩下的就是根据"包名.类名"使用反射创建对象。
getToClass()方法
// 获得类对象属性
private void getToClass(String classPath) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class> clazz = Class.forName(classPath); // 获得类加载器
// System.out.println("创建成功的类:"+clazz);
try { // 异常处理 即使clazz.getDeclaredConstructor().newInstance(); 遇到接口不能创建对象--程序也不会停止
Object bean = clazz.getDeclaredConstructor().newInstance(); // 创建对象--暴力创建
MyComponent beanName = clazz.getAnnotation(MyComponent.class); // 获得类上注解
if(!Objects.isNull(beanName)){ // 类上有注解的时候
String key=beanName.value(); // 获得注解中的value值--类名字
// System.out.println("key名字:"+key);
Field[] declaredFields = clazz.getDeclaredFields(); // 获得字段
for (Field field:declaredFields){ // 遍历字段
MyValue value = field.getAnnotation(MyValue.class); // 获得字段上的注解
field.setAccessible(true); // 打开权限 暴力注入 狠狠地注入
field.set(bean,value.value()); // 设置当前bean对象的字段
}
IOC.put(key,bean); // 存储到IOC中
}
}catch (Exception e){
System.out.println("不是类:"+e); // 如果遇到其他类型文件、接口等
}
}
包的绝对地址:/C:/Users/kk/IdeaProjects/IOCTest/target/classes/bean
包名.类名字:bean.BigStar
包名.类名字:bean.MyAnneTest
包名.类名字:bean.MyComponent
不是类:java.lang.NoSuchMethodException: bean.MyComponent.()
包名.类名字:bean.MyValue
不是类:java.lang.NoSuchMethodException: bean.MyValue.()
包名.类名字:bean.test.mycontor
包名.类名字:bean.test.test2.myse
容器中的数据:{mycontor=mycontor{hobb='李四'}, MyAnneTest=MyAnneTest{name='张三', hobby='打篮球'}, BigStar=BigStar{name='张三'}, myse=myse{name='后悔'}}
大多少自之定义注解都需要扫描包这一步,把getToClass()方法换一下就是其他的功能。ioc真正关键的还是@Autowired注解的实现,我放到下篇讲解。