每特提供的范本(主要代码)

/*** 手写Spring专题 注解版本注入bean* * @author 作者:余胜军**/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ClassPathXmlApplicationContext {// 扫包范围private String packageName;ConcurrentHashMap<String, Object> initBean = null;public ClassPathXmlApplicationContext(String packageName) {this.packageName = packageName;}// 使用beanID查找对象public Object getBean(String beanId) throws Exception {// 1.使用反射机制获取该包下所有的类已经存在bean的注解类List<Class> listClassesAnnotation = findClassExisService();if (listClassesAnnotation == null || listClassesAnnotation.isEmpty()) {throw new Exception("没有需要初始化的bean");}// 2.使用Java反射机制初始化对象initBean = initBean(listClassesAnnotation);if (initBean == null || initBean.isEmpty()) {throw new Exception("初始化bean为空!");}// 3.使用beanID查找查找对应bean对象Object object = initBean.get(beanId);// 4.使用反射读取类的属性,赋值信息attriAssign(object);return object;}// 使用反射读取类的属性,赋值信息public void attriAssign(Object object) throws IllegalArgumentException, IllegalAccessException {// 1.获取类的属性是否存在 获取bean注解Class<? extends Object> classInfo = object.getClass();Field[] declaredFields = classInfo.getDeclaredFields();for (Field field : declaredFields) {// 属性名称String name = field.getName();// 2.使用属性名称查找bean容器赋值Object bean = initBean.get(name);if (bean != null) {// 私有访问允许访问field.setAccessible(true);// 给属性赋值field.set(object, bean);continue;}}}// 使用反射机制获取该包下所有的类已经存在bean的注解类public List<Class> findClassExisService() throws Exception {// 1.使用反射机制获取该包下所有的类if (StringUtils.isEmpty(packageName)) {throw new Exception("扫包地址不能为空!");}// 2.使用反射技术获取当前包下所有的类List<Class<?>> classesByPackageName = ClassUtil.getClasses(packageName);// 3.存放类上有bean注入注解List<Class> exisClassesAnnotation = new ArrayList<Class>();// 4.判断该类上属否存在注解for (Class classInfo : classesByPackageName) {ExtService extService = (ExtService) classInfo.getDeclaredAnnotation(ExtService.class);if (extService != null) {exisClassesAnnotation.add(classInfo);continue;}}return exisClassesAnnotation;}// 初始化bean对象public ConcurrentHashMap<String, Object> initBean(List<Class> listClassesAnnotation)throws InstantiationException, IllegalAccessException {ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<String, Object>();for (Class classInfo : listClassesAnnotation) {// 初始化对象Object newInstance = classInfo.newInstance();// 获取父类名称String beanId = toLowerCaseFirstOne(classInfo.getSimpleName());concurrentHashMap.put(beanId, newInstance);}return concurrentHashMap;}// 首字母转小写public static String toLowerCaseFirstOne(String s) {if (Character.isLowerCase(s.charAt(0)))return s;elsereturn (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();}}

常用反射工具类

public class ClassUtil {/*** 取得某个接口下所有实现这个接口的类*/public static List<Class> getAllClassByInterface(Class c) {List<Class> returnClassList = null;if (c.isInterface()) {// 获取当前的包名String packageName = c.getPackage().getName();// 获取当前包下以及子包下所以的类List<Class<?>> allClass = getClasses(packageName);if (allClass != null) {returnClassList = new ArrayList<Class>();for (Class classes : allClass) {// 判断是否是同一个接口if (c.isAssignableFrom(classes)) {// 本身不加入进去if (!c.equals(classes)) {returnClassList.add(classes);}}}}}return returnClassList;}/** 取得某一类所在包的所有类名 不含迭代*/public static String[] getPackageAllClassName(String classLocation, String packageName) {// 将packageName分解String[] packagePathSplit = packageName.split("[.]");String realClassLocation = classLocation;int packageLength = packagePathSplit.length;for (int i = 0; i < packageLength; i++) {realClassLocation = realClassLocation + File.separator + packagePathSplit[i];}File packeageDir = new File(realClassLocation);if (packeageDir.isDirectory()) {String[] allClassName = packeageDir.list();return allClassName;}return null;}/*** 从包package中获取所有的Class* * @param pack* @return*/public static List<Class<?>> getClasses(String packageName) {// 第一个class类的集合List<Class<?>> classes = new ArrayList<Class<?>>();// 是否循环迭代boolean recursive = true;// 获取包的名字 并进行替换String packageDirName = packageName.replace('.', '/');// 定义一个枚举的集合 并进行循环来处理这个目录下的thingsEnumeration<URL> dirs;try {dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);// 循环迭代下去while (dirs.hasMoreElements()) {// 获取下一个元素URL url = dirs.nextElement();// 得到协议的名称String protocol = url.getProtocol();// 如果是以文件的形式保存在服务器上if ("file".equals(protocol)) {// 获取包的物理路径String filePath = URLDecoder.decode(url.getFile(), "UTF-8");// 以文件的方式扫描整个包下的文件 并添加到集合中findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);} else if ("jar".equals(protocol)) {// 如果是jar包文件// 定义一个JarFileJarFile jar;try {// 获取jarjar = ((JarURLConnection) url.openConnection()).getJarFile();// 从此jar包 得到一个枚举类Enumeration<JarEntry> entries = jar.entries();// 同样的进行循环迭代while (entries.hasMoreElements()) {// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件JarEntry entry = entries.nextElement();String name = entry.getName();// 如果是以/开头的if (name.charAt(0) == '/') {// 获取后面的字符串name = name.substring(1);}// 如果前半部分和定义的包名相同if (name.startsWith(packageDirName)) {int idx = name.lastIndexOf('/');// 如果以"/"结尾 是一个包if (idx != -1) {// 获取包名 把"/"替换成"."packageName = name.substring(0, idx).replace('/', '.');}// 如果可以迭代下去 并且是一个包if ((idx != -1) || recursive) {// 如果是一个.class文件 而且不是目录if (name.endsWith(".class") && !entry.isDirectory()) {// 去掉后面的".class" 获取真正的类名String className = name.substring(packageName.length() + 1, name.length() - 6);try {// 添加到classesclasses.add(Class.forName(packageName + '.' + className));} catch (ClassNotFoundException e) {e.printStackTrace();}}}}}} catch (IOException e) {e.printStackTrace();}}}} catch (IOException e) {e.printStackTrace();}return classes;}/*** 以文件的形式来获取包下的所有Class* * @param packageName* @param packagePath* @param recursive* @param classes*/public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,List<Class<?>> classes) {// 获取此包的目录 建立一个FileFile dir = new File(packagePath);// 如果不存在或者 也不是目录就直接返回if (!dir.exists() || !dir.isDirectory()) {return;}// 如果存在 就获取包下的所有文件 包括目录File[] dirfiles = dir.listFiles(new FileFilter() {// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)public boolean accept(File file) {return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));}});// 循环所有文件for (File file : dirfiles) {// 如果是目录 则继续扫描if (file.isDirectory()) {findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,classes);} else {// 如果是java类文件 去掉后面的.class 只留下类名String className = file.getName().substring(0, file.getName().length() - 6);try {// 添加到集合中去classes.add(Class.forName(packageName + '.' + className));} catch (ClassNotFoundException e) {e.printStackTrace();}}}}
}

个人书写简陋草本

public class ExtAnnotationClassPathXmlApplicationContext {private Map<String,String> classMap = new HashMap<String, String> ();public ExtAnnotationClassPathXmlApplicationContext(String packageName){List<Class<?>> classes = ClassUtil.getClasses(packageName);Iterator<Class<?>> it=classes.iterator();while(it.hasNext()){Class<?> c = it.next();ExtComponent declaredAnnotation = c.getDeclaredAnnotation(ExtComponent.class);if(declaredAnnotation!=null){classMap.put(c.getSimpleName(),c.getName());}}}public Object getBean(String beanName) throws Exception {String classFullName = classMap.get(beanName);if(org.springframework.util.StringUtils.isEmpty(classFullName)){throw  new Exception("未找到实例类");}Object object = Class.forName(classFullName).newInstance();return  object;}
}

手写SpringIOC注解版本相关推荐

  1. 手写 springIoc 注解版 ,实现@Service (beng),@Resource (依赖注入)

    手写springIoc 注解版 代码demo https://pan.baidu.com/s/1jyvLMDrg_bfpKmhtrTTZSQ 提取码:5ju1 代码目录结构 1.pom.xml < ...

  2. 手写springioc注解注入对象基本实现

    还是要养成写注释的习惯,首先一个代码想让人家看懂的情况下,记住一点,重构加设计模式,其实设计模式也比较好,达到别人可易读性,这是我要跟你讲的,而且你们不写注释是一个不好的习惯,你们一定要养成我善于重构 ...

  3. 手写springIOC、AOP

    手写springIOC.AOP 一.核心思想 1.IoC 1.1 什么是IoC? 1.2 IoC解决了什么问题 1.3 IoC和DI的区别 2.AOP 2.1 什么是AOP? 2.2 AOP解决的什么 ...

  4. 手写Spring-ioc 注入 jdk反射实现 绝对满足你的好奇心哦 解决怎么我写了一个注解就可以直接注入了?

    Spring-Ioc原理 解析 我们学完Spring后,大都就直接接着学习之后的内容啦,但是我想偶尔回过头来看一看,才能走的更远啊. 温故而知新. 关于Spring是怎么实现的?怎么我写了一个注解就可 ...

  5. 手写自定义注解实现思路

    我在这边问一下大家,你们说一下,我们现在想怎么样呢,这个时候大家记住一点,我们进入到正题,我们手写Spring的事务注解,在这边写一下,手写Spring的事务注解,既然手写的情况下,在这边我们假设,记 ...

  6. 手写一个简易版本的RPC

    前言 在1024程序员节前夕,学习技术是对节日最好的庆祝. 手写一个简易版的RPC,可以把模糊抽象的概念具像化,属于落地层面了. 1. RPC基本原理 RPC原理 2. 四个版本的迭代 注:api表示 ...

  7. C# list集合 重复元素 索引_源码分析专题10-纯手写JDK不同版本下的List接口

    纯手写集合框架(下一篇:LinkeList原理) 集合框架介绍 说明:对于以上的框架图有如下几点说明 1.所有集合类都位于java.util包下.Java的集合类主要由两个接口派生而出:Collect ...

  8. 用Maven手写SpringIOC(简易版)

    这里我是实现了如何获取配置文件中的bean对象 一.文件结构 二.需要的pom.xml依赖 <dependencies><dependency><groupId>d ...

  9. android手写简单mvp,[webpack]手写一个mvp版本的webpack

    let fs = require('fs'); let path = require('path'); let babylon = require('babylon'); // Babylon 把源码 ...

  10. [webpack]手写一个mvp版本的webpack

    let fs = require('fs'); let path = require('path');let babylon = require('babylon'); // Babylon 把源码转 ...

最新文章

  1. shingling算法——提取特征,m个hash函数做指纹计算,针对特征hash后变成m维向量,最后利用union-find算法计算相似性...
  2. logcat错误日志
  3. windows下vim高亮systemverilog
  4. javascript中Math.random()产生随机数总结
  5. rabbitmq 连接报错 An unexpected connection driver error occured(亲测)
  6. linux内核镜像解压,解压内核镜像
  7. 走的走的居然飞起来了……
  8. unity中单位是米还是厘米_401场地清理是什么,由施工单位做还是甲方做?造价中如何体现?...
  9. 【codevs1582】【BZOJ1228】E和D,博弈
  10. scala java抽象理解_scala – 抽象覆盖如何在Java代码方面起作用?
  11. Win10 UWP vs add github
  12. WLAN通信基础——WLAN物理层通信技术
  13. 题目:输入某年某月某日,判断这一天是这一年的第几天?
  14. Json本地校验工具--HiJson
  15. 菁搜FTP搜索引擎 photo2
  16. [转] 你没看过的囧人囧事大集合
  17. 三角形中重心、内心、外心、垂心向量计算公式
  18. 机器学习项目 - ctr 电商点击率预估
  19. 微信公众号与小程序对接文档
  20. 下载文件、根据链接生成二维码

热门文章

  1. 购买二手房时 众多购房者忽视办理土地证过户
  2. Web 的将来是语义的
  3. 记录下 k8s (1.14.2)使用kubeadm方式搭建和rancher搭建需要的镜像清单
  4. TCP/IP协议与Http协议的区别
  5. 对于拼接进去的html原来绑定的jq事件失效
  6. linux 笔记(2) 目录直接强行删除rm -rf *(删除当前目录所有的内容)
  7. 各版本的STP BPDU
  8. RHEL6.4 NFS文件共享服务搭建
  9. ubuntu 配置ip地址命令
  10. 谷歌眼中的云计算—李开复于浙江工商大学