@Data @AllArgsConstructor @NoArgsConstructor public class BeanDefinition { private String beanName; private Class beanClass; }最重要的类MyAnnotationConfigApplicationContext
在他的这个构造函数里,我们首先先根据他传入的包的名字,把这个包里面的所有类都扫描一次
SetfindBeanDefinitions函数beanDefinitions = findBeanDefinitions(pack);
首先他要扫描包下面的所有类,然后得到这些类以后,我要去遍历一下,找到添加了注解的类,如果我添加了这个注解的话,返回的值就不是null(Component componentAnnotation = clazz.getAnnotation(Component.class)),接下来的话,判断一下有没有自定义的beanName吧,如果没有的话,我就给他改一下
//这样子说明我直接就写了component注解而已,后面没给出名字,那我就给他搞个名字 //名字的话,我把全类名前面的干掉 //再把Account改成account这样子,比较规范 if ("".equals(beanName)){ String packageName = clazz.getPackage().getName(); packageName += "."; String clazzName = clazz.getName(); clazzName = clazzName.replaceAll(packageName,""); beanName = clazzName.substring(0,1).toLowerCase()+clazzName.substring(1); }
现在我可以把beanName和得到的类封装成前面写下的BeanDefinition了,然后放进集合里面,为什么要集合呢,因为要去重.
//beanDefinitions集合放入通过封装的BeanDefinition对象 //BeanDefinition里面的field有bean的名字和类,现在封装好放进集合 //之所以选择set,是因为要去重,有一个就足够了 beanDefinitions.add(new BeanDefinition(beanName,clazz));下面是完整的该函数代码
public SetfindBeanDefinitions(String pack){ Set beanDefinitions = new HashSet<>(); //获取包下面的所有类 Set > classes = MyTools.getClasses(pack); //遍历这些类,找到添加了注解的类 Iterator > iterator = classes.iterator(); while (iterator.hasNext()){ Class> clazz = iterator.next(); //返回对应注解的Class对象 Component componentAnnotation = clazz.getAnnotation(Component.class); if (componentAnnotation!=null){ //获取component注解的值 String beanName = componentAnnotation.value(); //这样子说明我直接就写了component注解而已,后面没给出名字,那我就给他搞个名字 //名字的话,我把全类名前面的干掉 //再把Account改成account这样子,比较规范 if ("".equals(beanName)){ String packageName = clazz.getPackage().getName(); packageName += "."; String clazzName = clazz.getName(); clazzName = clazzName.replaceAll(packageName,""); beanName = clazzName.substring(0,1).toLowerCase()+clazzName.substring(1); } //beanDefinitions集合放入通过封装的BeanDefinition对象 //BeanDefinition里面的field有bean的名字和类,现在封装好放进集合 //之所以选择set,是因为要去重,有一个就足够了 beanDefinitions.add(new BeanDefinition(beanName,clazz)); } } return beanDefinitions; }
找到所有bean放进集合以后,下一步要做的呢,就是放进ioc容器里面,ioc容器这里用的是
private Mapioc = new HashMap<>();
接下来从集合里面拿出我的BeanDefinition,然后分别拿出beanName和beanCLass,通过类对象的getConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象。
Object object = clazz.getConstructor().newInstance();
clazz.getDeclaredFields()拿到所有的字段,遍历所有的字段,老样子判断添加了@Value注解的字段
拿到字段名字以后去制作set方法
String value = valueAnnotation.value(); //拿到字段名字 String fieldName = declaredField.getName(); //要去做这个字段的set方法 String methodName = "set" +fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); Method method = clazz.getMethod(methodName,declaredField.getType());
要完成类型赋值的话,得转一下类型,不然的话到时候直接就报错了,类型不匹配
switch (declaredField.getType().getName()) { case "java.lang.Integer": val = Integer.parseInt(value); break; case "java.lang.String": val = value; break; case "java.lang.Float": val = Float.parseFloat(value); break; }
method.invoke(“要调用的方法的名字所隶属的对象实体”,方法的参数值);
method.invoke(object,val);
搞定之后放进ioc容器了,用beanName去对应
ioc.put(beanName,object);该函数的代码
public void createBean(Set轮到自动装载了beanDefinitions){ Iterator iterator = beanDefinitions.iterator(); while (iterator.hasNext()) { BeanDefinition beanDefinition = iterator.next(); //从我封装好的对象里面我拿出我的类 Class clazz = beanDefinition.getBeanClass(); //从我封装好的对象里面拿出我的beanName String beanName = beanDefinition.getBeanName(); try { //通过类对象的getConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象 Object object = clazz.getConstructor().newInstance(); //获取此类中的所有字段 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { //getAnnotation(),如果不是这样的注解,就返回null Value valueAnnotation = declaredField.getAnnotation(Value.class); if (valueAnnotation!=null){ String value = valueAnnotation.value(); //拿到字段名字 String fieldName = declaredField.getName(); //要去做这个字段的set方法 String methodName = "set" +fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); Method method = clazz.getMethod(methodName,declaredField.getType()); //完成数据类型转换 Object val = null; //拿到数据类型的名字,来完成类型赋值 switch (declaredField.getType().getName()) { case "java.lang.Integer": val = Integer.parseInt(value); break; case "java.lang.String": val = value; break; case "java.lang.Float": val = Float.parseFloat(value); break; } //传入值 //method.invoke("要调用的方法的名字所隶属的对象实体",方法的参数值); method.invoke(object,val); } } //搞定之后放进ioc容器了 ioc.put(beanName,object); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }
老样子,传过去的还是集合,遍历一次所有的字段,看看有没有@Authwired注解的,看看是不是为null
AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
如果找到了,那就是添加了这个注解的,那我还得再找一下里面有没有@Qualifier注解的
Qualifier qualifier = declaredField.getAnnotation(Qualifier.class);
如果有的话,那我就得通过这个bean的名字去ioc容器拿出来
接下来拿到字段名字和方法等等这些
String beanName = qualifier.value(); //通过bean的名字去ioc容器里面把bean拿出来 //ioc容器我用的是hashMap Object bean = getBean(beanName); //拿字段名 String fieldName = declaredField.getName(); String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); Method method = clazz.getMethod(methodName, declaredField.getType());
//method.invoke("要调用的方法的名字所隶属的对象实体",方法的参数值); //把另外一个bean传入,不然的话打印出来是null的 method.invoke(object,bean);该函数的完全代码
public void autowireObject(Set该类的完全代码beanDefinitions){ Iterator iterator = beanDefinitions.iterator(); while (iterator.hasNext()){ BeanDefinition beanDefinition = iterator.next(); //因为我的这个beanDefinition对象里面,有一个beanName和一个BeanClass(放类的) Class clazz = beanDefinition.getBeanClass(); //拿出这个类的所有字段 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { //看看这个字段有没有AutoWired这个注解 AutoWired annotation = declaredField.getAnnotation(AutoWired.class); if (annotation!=null){ //看看有没有Qualifier这种自定义名字的注解 Qualifier qualifier = declaredField.getAnnotation(Qualifier.class); if (qualifier!=null){ //我用Qualifier自定义名字了 //byName try { String beanName = qualifier.value(); //通过bean的名字去ioc容器里面把bean拿出来 //ioc容器我用的是hashMap Object bean = getBean(beanName); //拿字段名 String fieldName = declaredField.getName(); String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); Method method = clazz.getMethod(methodName, declaredField.getType()); Object object = getBean(beanDefinition.getBeanName()); //传入值 //method.invoke("要调用的方法的名字所隶属的对象实体",方法的参数值); //把另外一个bean传入,不然的话打印出来是null的 method.invoke(object,bean); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }else{ //byType } } } } }
```java public class MyAnnotationConfigApplicationContext { private Mapioc = new HashMap<>(); public MyAnnotationConfigApplicationContext(String pack){ //遍历包,返回所有的目标类 Set beanDefinitions = findBeanDefinitions(pack); Iterator iterator = beanDefinitions.iterator(); //根据原材料来创建Bean createBean(beanDefinitions); //自动装载 autowireObject(beanDefinitions); } public void autowireObject(Set beanDefinitions){ Iterator iterator = beanDefinitions.iterator(); while (iterator.hasNext()){ BeanDefinition beanDefinition = iterator.next(); //因为我的这个beanDefinition对象里面,有一个beanName和一个BeanClass(放类的) Class clazz = beanDefinition.getBeanClass(); //拿出这个类的所有字段 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { //看看这个字段有没有AutoWired这个注解 AutoWired annotation = declaredField.getAnnotation(AutoWired.class); if (annotation!=null){ //看看有没有Qualifier这种自定义名字的注解 Qualifier qualifier = declaredField.getAnnotation(Qualifier.class); if (qualifier!=null){ //我用Qualifier自定义名字了 //byName try { String beanName = qualifier.value(); //通过bean的名字去ioc容器里面把bean拿出来 //ioc容器我用的是hashMap Object bean = getBean(beanName); //拿字段名 String fieldName = declaredField.getName(); String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); Method method = clazz.getMethod(methodName, declaredField.getType()); Object object = getBean(beanDefinition.getBeanName()); //传入值 //method.invoke("要调用的方法的名字所隶属的对象实体",方法的参数值); //把另外一个bean传入,不然的话打印出来是null的 method.invoke(object,bean); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }else{ //byType } } } } } public Object getBean(String beanName){ return ioc.get(beanName); } //根据集合来创建bean public void createBean(Set beanDefinitions){ Iterator iterator = beanDefinitions.iterator(); while (iterator.hasNext()) { BeanDefinition beanDefinition = iterator.next(); //从我封装好的对象里面我拿出我的类 Class clazz = beanDefinition.getBeanClass(); //从我封装好的对象里面拿出我的beanName String beanName = beanDefinition.getBeanName(); try { //通过类对象的getConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象 Object object = clazz.getConstructor().newInstance(); //获取此类中的所有字段 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { //getAnnotation(),如果不是这样的注解,就返回null Value valueAnnotation = declaredField.getAnnotation(Value.class); if (valueAnnotation!=null){ String value = valueAnnotation.value(); //拿到字段名字 String fieldName = declaredField.getName(); //要去做这个字段的set方法 String methodName = "set" +fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); Method method = clazz.getMethod(methodName,declaredField.getType()); //完成数据类型转换 Object val = null; //拿到数据类型的名字,来完成类型赋值 switch (declaredField.getType().getName()) { case "java.lang.Integer": val = Integer.parseInt(value); break; case "java.lang.String": val = value; break; case "java.lang.Float": val = Float.parseFloat(value); break; } //传入值 //method.invoke("要调用的方法的名字所隶属的对象实体",方法的参数值); method.invoke(object,val); } } //搞定之后放进ioc容器了 ioc.put(beanName,object); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } public Set findBeanDefinitions(String pack){ Set beanDefinitions = new HashSet<>(); //获取包下面的所有类 Set > classes = MyTools.getClasses(pack); //遍历这些类,找到添加了注解的类 Iterator > iterator = classes.iterator(); while (iterator.hasNext()){ Class> clazz = iterator.next(); //返回对应注解的Class对象 Component componentAnnotation = clazz.getAnnotation(Component.class); if (componentAnnotation!=null){ //获取component注解的值 String beanName = componentAnnotation.value(); //这样子说明我直接就写了component注解而已,后面没给出名字,那我就给他搞个名字 //名字的话,我把全类名前面的干掉 //再把Account改成account这样子,比较规范 if ("".equals(beanName)){ String packageName = clazz.getPackage().getName(); packageName += "."; String clazzName = clazz.getName(); clazzName = clazzName.replaceAll(packageName,""); beanName = clazzName.substring(0,1).toLowerCase()+clazzName.substring(1); } //beanDefinitions集合放入通过封装的BeanDefinition对象 //BeanDefinition里面的field有bean的名字和类,现在封装好放进集合 //之所以选择set,是因为要去重,有一个就足够了 beanDefinitions.add(new BeanDefinition(beanName,clazz)); } } return beanDefinitions; } }
## 需要的实体类 ```java @Component @Data public class Account { @Value("1") private Integer id; @Value("张三") private String name; @Value("22") private Integer age; @AutoWired @Qualifier("myOrder") private Order order; }
@Data @Component("myOrder") public class Order { @Value("jyu") private String address; }@Component注解
//这种后面是type的,对应的是接口、类、枚举 @Target(ElementType.TYPE) //runtime,注解不仅被保存到class文件中,就算jvm加载class文件以后,依然存在 @Retention(RetentionPolicy.RUNTIME) public @interface Component { String value() default ""; }@Value注解
//这种后面对应的是field的,对应的是字段和枚举的常量 @Target(ElementType.FIELD) //runtime,注解不仅被保存到class文件中,就算jvm加载class文件以后,依然存在 @Retention(RetentionPolicy.RUNTIME) public @interface Value { String value(); }@Qualifier注解
//这种后面对应的是field的,对应的是字段和枚举的常量 @Target(ElementType.FIELD) //runtime,注解不仅被保存到class文件中,就算jvm加载class文件以后,依然存在 @Retention(RetentionPolicy.RUNTIME) public @interface Qualifier { String value(); }@AutoWired注解
//这种后面对应的是field的,对应的是字段和枚举的常量 @Target(ElementType.FIELD) //runtime,注解不仅被保存到class文件中,就算jvm加载class文件以后,依然存在 @Retention(RetentionPolicy.RUNTIME) public @interface AutoWired { }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)