前言

本文使用注解方式来读取bean类,并解决bean之间的依赖。其中Component和Value注解直接copy自Spring,Resource注解来自javax。

扫描包中的所有类

还是以前文提到的beanA和beanB两个model类为例(省略set和get方法)。

@Component
public class BeanA {@Value("studentA")private String title;@Resourceprivate BeanB beanB;
}@Component
public class BeanB {@Value("studentB")private String title;
}

根据前文,我们可以发现,要实现bean工厂功能,首先要将bean信息加载到内存(由配置文件方式转化为“以类的方式”存储)。
在本文中,虽然配置文件没了,但思路是一致的。我们要根据注解,采集bean信息,存储在map中。注解和配置文件方式的一个不同是:配置文件是配什么bean加载什么,而注解方式,则需要我们扫描目标pacakge中的所有bean。

public class Main {private static Map<String,Class> beanId2Clazz = new HashMap<String,Class>();// 将一个字符串的首字符小写private static String smallCaseFirstChar(String prop){char ch = (char) (prop.charAt(0) + 32);return prop.replaceFirst(prop.charAt(0) + "", ch + "");}public static void main(String[] args) throws Exception {// 扫描包中包含的类(即扫描目的包所在文件的子文件)String packageName = "org.lqk.lspring.bean";String rootPath = Main3.class.getResource("/").getPath();File file = new File(rootPath + File.separator +  packageName.replace(".", File.separator));String[] fileNames = file.list();// 扫描for(String fileName : fileNames){String className = fileName.substring(0,fileName.length() - ".class".length());String fullClassName = packageName + "." + className;Class clazz = Class.forName(fullClassName);Component cop = (Component) clazz.getAnnotation(Component.class);if(null != cop){String beanId = cop.value();if(StringUtils.isEmpty(beanId)){beanId = smallCaseFirstChar(className);}beanId2Clazz.put(beanId, clazz);}}}
}

关于扫描一个包中所有的类,有现成的org.reflections包,此处为了减少##读者的理解曲线,就不提了。

当加载完bean的信息后,整个步骤已经跟前文很像了。

加载beanB类

public class Main {private static Map<String,Class> beanId2Clazz = new HashMap<String,Class>();public static void load() throws ClassNotFoundException {// 即为上述的main类}public static Object getBean(String beanId) throws Exception{Class clazz = beanId2Clazz.get(beanId);if(null == clazz){return null;}Object obj = clazz.newInstance();Field[] fields = clazz.getDeclaredFields();// 处理带value注解的属性for(Field field : fields){Value v = field.getAnnotation(Value.class);if(null == v){continue;}String propertyValue = v.value();Method m = clazz.getMethod("set" + bigCaseFirstChar(field.getName()), String.class);m.invoke(obj, propertyValue);}return obj;}public static void main(String[] args) throws Exception {load();BeanB beanB = (BeanB)getBean("beanB");System.out.println(beanB.getTitle());}
}

加载beanA类

public class Main2 {private static Map<String,Class> beanId2Clazz = new HashMap<String,Class>();public static void load() throws ClassNotFoundException {// 不再赘述}public static Object getBean(String beanId) throws Exception{Class clazz = beanId2Clazz.get(beanId);if(null == clazz){return null;}Object obj = clazz.newInstance();Field[] fields = clazz.getDeclaredFields();for(Field field : fields){Method m = clazz.getMethod("set" + bigCaseFirstChar(field.getName()), field.getType());Value v = field.getAnnotation(Value.class);// 处理value注解if(null != v){String propertyValue = v.value();m.invoke(obj, propertyValue);}Resource r = field.getAnnotation(Resource.class);// 处理resource注解if(null != r){String propertyBeanId = r.name();if(StringUtils.isEmpty(propertyBeanId)){propertyBeanId = smallCaseFirstChar(field.getType().getSimpleName());}// 递归处理Object propertyObj = getBean(propertyBeanId);m.invoke(obj, propertyObj);}}return obj;}public static void main(String[] args) throws Exception {load();BeanA beanA = (BeanA)getBean("beanA");System.out.println(beanA.getBeanB().getTitle());}
}

至此,我们已经完全使用注解方式创建了一个bean工厂,下文将会尝试把注解和配置文件两种方式整合到一块儿。

转载于:https://www.cnblogs.com/qiankunli/p/4943806.html

自己动手写spring(三) 支持注解方式相关推荐

  1. spring AOP自定义注解方式实现日志管理

    转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...

  2. Spring的AOP-AspectJ注解方式

    目录 Spring的AOP-AspectJ注解方式 1.创建类,在类里面定义方法 2.创建增强类 3.进行通知的配置 (1)在Spring 配置文件中,开启直接扫描 (2)使用注解创建User 和 U ...

  3. 自己动手写word2vec (三):构建Huffman树

    系列所有帖子 自己动手写word2vec (一):主要概念和流程 自己动手写word2vec (二):统计词频 自己动手写word2vec (三):构建Huffman树 自己动手写word2vec ( ...

  4. spring三种注入方式

    设置Spring的作用域 或者使用枚举值设置 单例和多里使用场景 自动注入 @Primary 一个接口有多个实现被spring管理吗,在依赖注入式,spring会不知道注入哪个实现类就会抛出NoUni ...

  5. Spring整合Mybatis注解方式

    Spring整合Mybatis(注解方式) 目录 Spring整合Mybatis(注解方式) 环境准备 纯注解方式 配置类具体内容 测试类具体内容 环境准备 jar包: Spring所需依赖:spri ...

  6. springmvc3.2+spring+hibernate4全注解方式整合(一)

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...

  7. 邮件发送 --- 纯Java、JavaWeb、Spring三种实现方式

    邮件发送学习笔记~ 一.邮件发送介绍 要在网络上实现邮件功能,必须要有专门的邮件服务器! 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中! ...

  8. spring学习--基于注解方式创建对象AOP

    概念 下面四个注解功能是一样的,都可以用来创建 bean 实例 ​ (1)@Component ​ (2)@Service ​ (3)@Controller ​ (4)@Repository 1.引入 ...

  9. Spring Boot基于注解方式处理接口数据脱敏

    1.定义注解 创建Spring Boot项目添加以下依赖 <dependencies><dependency><groupId>org.springframewor ...

最新文章

  1. antd 中 Tree 的使用-默认选中问题
  2. 做一个略调皮的个人主页--相册与随笔篇
  3. VTK:小部件之BoxWidget
  4. koa --- 跨域,解析POST参数、路由配置
  5. web.config配置数据库连接
  6. Java—抽象类和接口的区别
  7. 不要进行过度设计,某一层存在真的有意义吗?是否可以更简单。
  8. vue的边距怎么设置_Vue项目如何适应浏览器,去除容器控件与浏览器四周的距离...
  9. 网络管理:3分钟排障秘技,一招胜过十年功
  10. bootstrap学习笔记-(1-初识bootstrap)
  11. proteus 7.8下载链接
  12. 工业交换机与普通交换机区别
  13. 如何知道股票里面有庄
  14. 列宁名言、警句、格言、语录
  15. JAVA学习day30--方法的重写
  16. 赛场上的 AI 务实派:经典招式,也能作出“新解”!
  17. 室内设计优美语句_赞美家装设计师的句子
  18. 一键安装微信已完成,编号10,欢迎品尝
  19. Pr 案例:制作快闪转场效果
  20. ORA-00001: unique constraint (...) violated解决方案

热门文章

  1. 计算机网络课程设计之基于 IP 多播的网络会议程序
  2. 3倍根号x加1分之一c语言,用C语言将一个数开根号后再取倒数的方法
  3. divcss布局模板代码_CSS3布局(前端所必须要掌握)
  4. 信息安全工程师笔记-国产密码算法(国密)概念
  5. Android逆向笔记-查看app的log打印(含调试方式打开)
  6. 系统架构师学习笔记-操作系统(一)
  7. MySQL入门之扩展匹配符、order by、limit、union、group by、having子句
  8. 专业课程设计之客户与服务器程序的同步与通信机制的设计(三)数据共享和线程
  9. php mysql 操作函数_PHP操作mysql函数详解,mysql和php交互函数
  10. mysql round 0.1111_听说Mysql你很豪横?-------------分分钟带你玩转SQL高级查询语句(库函数,存储过程)...