自己动手写spring(三) 支持注解方式
前言
本文使用注解方式来读取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(三) 支持注解方式相关推荐
- spring AOP自定义注解方式实现日志管理
转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...
- Spring的AOP-AspectJ注解方式
目录 Spring的AOP-AspectJ注解方式 1.创建类,在类里面定义方法 2.创建增强类 3.进行通知的配置 (1)在Spring 配置文件中,开启直接扫描 (2)使用注解创建User 和 U ...
- 自己动手写word2vec (三):构建Huffman树
系列所有帖子 自己动手写word2vec (一):主要概念和流程 自己动手写word2vec (二):统计词频 自己动手写word2vec (三):构建Huffman树 自己动手写word2vec ( ...
- spring三种注入方式
设置Spring的作用域 或者使用枚举值设置 单例和多里使用场景 自动注入 @Primary 一个接口有多个实现被spring管理吗,在依赖注入式,spring会不知道注入哪个实现类就会抛出NoUni ...
- Spring整合Mybatis注解方式
Spring整合Mybatis(注解方式) 目录 Spring整合Mybatis(注解方式) 环境准备 纯注解方式 配置类具体内容 测试类具体内容 环境准备 jar包: Spring所需依赖:spri ...
- springmvc3.2+spring+hibernate4全注解方式整合(一)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...
- 邮件发送 --- 纯Java、JavaWeb、Spring三种实现方式
邮件发送学习笔记~ 一.邮件发送介绍 要在网络上实现邮件功能,必须要有专门的邮件服务器! 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中! ...
- spring学习--基于注解方式创建对象AOP
概念 下面四个注解功能是一样的,都可以用来创建 bean 实例 (1)@Component (2)@Service (3)@Controller (4)@Repository 1.引入 ...
- Spring Boot基于注解方式处理接口数据脱敏
1.定义注解 创建Spring Boot项目添加以下依赖 <dependencies><dependency><groupId>org.springframewor ...
最新文章
- antd 中 Tree 的使用-默认选中问题
- 做一个略调皮的个人主页--相册与随笔篇
- VTK:小部件之BoxWidget
- koa --- 跨域,解析POST参数、路由配置
- web.config配置数据库连接
- Java—抽象类和接口的区别
- 不要进行过度设计,某一层存在真的有意义吗?是否可以更简单。
- vue的边距怎么设置_Vue项目如何适应浏览器,去除容器控件与浏览器四周的距离...
- 网络管理:3分钟排障秘技,一招胜过十年功
- bootstrap学习笔记-(1-初识bootstrap)
- proteus 7.8下载链接
- 工业交换机与普通交换机区别
- 如何知道股票里面有庄
- 列宁名言、警句、格言、语录
- JAVA学习day30--方法的重写
- 赛场上的 AI 务实派:经典招式,也能作出“新解”!
- 室内设计优美语句_赞美家装设计师的句子
- 一键安装微信已完成,编号10,欢迎品尝
- Pr 案例:制作快闪转场效果
- ORA-00001: unique constraint (...) violated解决方案
热门文章
- 计算机网络课程设计之基于 IP 多播的网络会议程序
- 3倍根号x加1分之一c语言,用C语言将一个数开根号后再取倒数的方法
- divcss布局模板代码_CSS3布局(前端所必须要掌握)
- 信息安全工程师笔记-国产密码算法(国密)概念
- Android逆向笔记-查看app的log打印(含调试方式打开)
- 系统架构师学习笔记-操作系统(一)
- MySQL入门之扩展匹配符、order by、limit、union、group by、having子句
- 专业课程设计之客户与服务器程序的同步与通信机制的设计(三)数据共享和线程
- php mysql 操作函数_PHP操作mysql函数详解,mysql和php交互函数
- mysql round 0.1111_听说Mysql你很豪横?-------------分分钟带你玩转SQL高级查询语句(库函数,存储过程)...