要实现的功能:

  1. 将对象的实例化交给自定的ioc容器.
  2. 通过注解的方式对接口进行依赖注入
  3. 通过getBean("userName")方法那到对象,使用对象的方法
  • 首先,创建一个对象,定义对象的构造函数

      1. package cn.lisongyu.ioc.demo.bean;
      2. import cn.lisongyu.ioc.annotation.Component;
      3. /**
      4. * @author lisongyu
      5. * @ClassName cn.lisongyu.ioc.demo.bean.UserBean
      6. * @description userbean
      7. * @create 2018年11月22日 11:08
      8. */
      9. @Component //自定义的组件,让ioc容器扫描带有指定注解的类,将当前类装配到ioc容器中
      10. public class UserBean {
      11. @Autowired //自定义的注入注解
      12. private Service service;
      13. public UserBean() {
      14. System.out.println("UserBean -> instance");
      15. }
      16. public void getUser(){
      17. service.test(); //接口的方法,如果注入失败,将报空指针异常
      18. System.out.println("用户详情展示");
      19. }
      20. }
      1. package cn.lisongyu.ioc.demo.a.b.c;
      2. import cn.lisongyu.ioc.annotation.Component;
      3. import cn.lisongyu.ioc.demo.a.b.Service;
      4. /**
      5. * @author lisongyu
      6. * @ClassName cn.lisongyu.ioc.demo.a.b.c.TestService
      7. * @description Service实现类
      8. * @create 2018年11月22日 11:22
      9. */
      10. @Component
      11. public class TestService implements Service {
      12. public TestService() {
      13. System.out.println("TestService -> instance");
      14. }
      15. @Override
      16. public void test() {
      17. System.out.println("Service 接口实现方法");
      18. }
      19. }
      1. package cn.lisongyu.ioc.demo.a.b;
      2. /**
      3. * /**
      4. *
      5. * @author lisongyu
      6. * @ClassName cn.lisongyu.ioc.demo.a.b.Service
      7. * @description Service接口
      8. * @create 2018年11月22日 17:31
      9. */
      10. public interface Service {
      11. void test();
      12. }
  • 创建自定义的注解

      1. package cn.lisongyu.ioc.annotation;
      2. import java.lang.annotation.ElementType;
      3. import java.lang.annotation.Retention;
      4. import java.lang.annotation.RetentionPolicy;
      5. import java.lang.annotation.Target;
      6. //依赖注入注解
      7. @Retention(RetentionPolicy.RUNTIME)
      8. @Target(ElementType.FIELD) //只能注解到字段上
      9. public @interface Autowired {
      10. }
      1. package cn.lisongyu.ioc.annotation;
      2. import java.lang.annotation.ElementType;
      3. import java.lang.annotation.Retention;
      4. import java.lang.annotation.RetentionPolicy;
      5. import java.lang.annotation.Target;
      6. //组件注解
      7. @Retention(RetentionPolicy.RUNTIME) //程序运行时执行
      8. @Target(ElementType.TYPE) //该注解指定标注的位置 TYPE:类
      9. public @interface Component {
      10. }
  • 定义一个接口,用来获取bean对象的方法

      1. package cn.lisongyu.ioc.context;
      2. /**
      3. * /**
      4. * Application 接口
      5. * @author lisongyu
      6. * @ClassName cn.lisongyu.ioc.context.Application
      7. * @description
      8. * @create 2018年11月22日 11:24
      9. */
      10. public interface Application {
      11. Object getBean(String beanName);
      12. }
      1. package cn.lisongyu.ioc.context;
      2. import cn.lisongyu.ioc.annotation.Component;
      3. import java.io.File;
      4. import java.io.FileFilter;
      5. import java.net.URL;
      6. import java.sql.SQLOutput;
      7. import java.util.ArrayList;
      8. import java.util.List;
      9. import java.util.Map;
      10. import java.util.SortedMap;
      11. import java.util.concurrent.ConcurrentHashMap;
      12. /**
      13. * @author lisongyu
      14. * @ClassName cn.lisongyu.ioc.context.ApplicationImpl
      15. * @description Application的实现类
      16. * @create 2018年11月22日 11:24
      17. */
      18. public class ApplicationImpl implements Application {
      19. //定义存放所有类对象的集合
      20. private List<Class<?>> classList = new ArrayList<>();
      21. //定义存放类的实例对象的集合
      22. private Map<String,Object> instanceMap = new ConcurrentHashMap<>();
      23. //无参构造
      24. public ApplicationImpl() {
      25. }
      26. /**
      27. * 有参构造,通过传入的包路径来实现扫描
      28. * @param basePackage
      29. */
      30. public ApplicationImpl(String basePackage) {
      31. //扫描包路径
      32. doScan(basePackage);
      33. //实例化
      34. doIoc();
      35. System.out.println(instanceMap);
      36. //依赖注入
      37. doDi();
      38. }
      39. /**
      40. * 实例化对象
      41. */
      42. private void doIoc() {
      43. //首先判断一下当前类集合中是否含有元素
      44. if (classList == null){
      45. return;
      46. }
      47. //遍历集合
      48. classList.forEach((clz) ->{
      49. try {
      50. //通过类对象,实例化一个对象
      51. Object instance = clz.newInstance();
      52. //创建key
      53. String key = getKeyName(clz.getSimpleName());
      54. //存放到map集合中
      55. //如果集合中存在则报错
      56. if (instanceMap.containsKey(key)){
      57. throw new RuntimeException("相同的类名");
      58. }
      59. //放入ioc容器中
      60. instanceMap.put(key,instance);
      61. //判断当前类是否实现了接口
      62. Class<?>[] interfaces = clz.getInterfaces();
      63. for (Class<?> inter : interfaces) {
      64. instanceMap.put(inter.getName(),instance);
      65. }
      66. } catch (InstantiationException e) {
      67. e.printStackTrace();
      68. } catch (IllegalAccessException e) {
      69. e.printStackTrace();
      70. }
      71. });
      72. }
      73. //改名,获取一个首字母小写的类名
      74. private String getKeyName(String simpleName) {
      75. char[] chars = simpleName.toCharArray();
      76. chars[0] += 32;
      77. return String.valueOf(chars);
      78. }
      79. //依赖注入
      80. private void doDi() {
      81. //首先判断实例对象是否有
      82. if (instanceMap.size() == 0)
      83. return;
      84. //遍历所有的实例对象
      85. instanceMap.forEach((k,v) -> {
      86. Object instance = v;
      87. //注入实体对象
      88. Object injectionInstance = null;
      89. //通过反射获取类对象
      90. Class<?> clz = v.getClass();
      91. //获取当前类对象的所有声明的字段
      92. Field[] fields = clz.getDeclaredFields();
      93. //循环遍历所有字段
      94. for (Field field : fields) {
      95. //判断字段是否含有@Autowired注解
      96. if(field.isAnnotationPresent(Autowired.class)){
      97. String name = field.getType().getName();
      98. injectionInstance = this.instanceMap.get(name);
      99. }
      100. // 通过反射注入到该属性中
      101. field.setAccessible(true);
      102. try {
      103. field.set(instance,injectionInstance);
      104. } catch (IllegalAccessException e) {
      105. e.printStackTrace();
      106. }
      107. }
      108. });
      109. }
      110. //包扫描方法
      111. private void doScan(String basePackage) {
      112. //获取当前包的位置
      113. URL resource = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/"));
      114. //创建一个文件对象
      115. File file = new File(resource.getPath());
      116. //遍历文件
      117. File[] fileNames = file.listFiles(new FileFilter() {
      118. @Override
      119. public boolean accept(File childFile) {
      120. //判断当前文件是否是一个文件夹
      121. if (childFile.isDirectory()){
      122. //如果是文件夹,递归,获取所有的class文件
      123. doScan(basePackage+"."+childFile.getName());
      124. }else {
      125. //判断当前文件是否是一个类文件
      126. if (childFile.getName().endsWith(".class")){
      127. String classPath = basePackage + "." + childFile.getName().replaceAll("\\.class", "");
      128. Class<?> clz = null;
      129. try {
      130. clz = Class.forName(classPath);
      131. //判断是否是有@Component注解的类
      132. if (clz.isAnnotationPresent(Component.class)){
      133. classList.add(clz);
      134. }
      135. } catch (ClassNotFoundException e) {
      136. e.printStackTrace();
      137. }
      138. }
      139. }
      140. return false;
      141. }
      142. });
      143. }
      144. @Override
      145. public Object getBean(String beanName) {
      146. return this.instanceMap.get(beanName);
      147. }
      148. }
  • 运行main()

      1. package cn.lisongyu.ioc;
      2. import cn.lisongyu.ioc.context.Application;
      3. import cn.lisongyu.ioc.context.ApplicationImpl;
      4. import cn.lisongyu.ioc.demo.bean.UserBean;
      5. import java.util.*;
      6. /**
      7. * Hello world!
      8. *
      9. */
      10. public class App
      11. {
      12. public static void main( String[] args ) {
      13. //包路径
      14. Application app = new ApplicationImpl("cn.lisongyu.ioc.demo");
      15. UserBean userBean = (UserBean) app.getBean("userBean");
      16. userBean.getUser();
      17. }
      18. }
  • 结果:

    1. TestService -> instance //接口实现类的初始化
    2. UserBean -> instance //对象类的初始化
    3. {cn.lisongyu.ioc.demo.a.b.Service=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, testService=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, userBean=cn.lisongyu.ioc.demo.bean.UserBean@6d03e736} //装配到容器中的类
    4. Service 接口实现方法 //service.test();
    5. 用户详情展示 //userBean.getUser();

自定义一个IOC框架的更多相关文章

  1. Android Afinal框架学习(二) FinalActivity 一个IOC框架

    框架地址:https://github.com/yangfuhai/afinal 相应的源代码: net.tsz.afinal.annotation.view.* FinalActivity Fina ...

  2. 解读 IoC 框架 InversifyJS

    原文链接 InversityJS 是一个 IoC 框架.IoC(Inversion of Control) 包括依赖注入(Dependency Injection) 和依赖查询(Dependency ...

  3. Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架

    CSDN:码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51957819 前言 Retrofit用法和介绍的文章实在是多的数不清 ...

  4. 【Android开发经验】来,咱们自己写一个Android的IOC框架!

    到眼下位置.afinal开发框架也是用了好几个月了,还记得第一次使用凝视完毕控件的初始化和事件绑定的时候,当时的心情是多么的兴奋- -代码居然能够这样写!然后随着不断的学习,也慢慢的对IOC框架和注解 ...

  5. ASP.NET Core 6框架揭秘实例演示[28]:自定义一个服务器

    作为ASP.NET Core请求处理管道的"龙头"的服务器负责监听和接收请求并最终完成对请求的响应.它将原始的请求上下文描述为相应的特性(Feature),并以此将HttpCont ...

  6. 轻量级IOC框架SwiftSuspenders

    该框架的1.6版本位于https://github.com/tschneidereit/SwiftSuspenders/blob/the-past/,现在已经出了重新架构的2.0版本,所以我决定先研究 ...

  7. 轻量级IOC框架:Ninject (下)

    一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们 ...

  8. IOC框架Ninject实践总结

    原文地址:http://www.cnblogs.com/jeffwongishandsome/archive/2012/04/15/2450462.html IOC框架Ninject实践总结 一.控制 ...

  9. 国人编写的开源 .net Ioc 框架——My.Ioc 简介

    My.Ioc 是作者开发的一款开源 IoC/DI 框架,下载地址在此处.它具有下面一些特点: 高效 在实现手段上,My.Ioc 通过使用泛型.缓存.动态生成代码.延迟注册.尽量使用抽象类而非接口等方式 ...

随机推荐

  1. Python进阶之函数式编程

    函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计 ...

  2. 解决一个Ubuntu中编译NEON优化的OpenCV的错误

    在Ubuntu 16中编译开启NEON优化的Opencv时,遇到libpng编译是使用汇编代码的错误,完整错误见文章末尾.通过查询发现解决方案是安装跨平台编译器,安装代码如下: sudo apt-ge ...

  3. 如何在WIN10内置Ubuntu中有多个terminal

    使用的是tmux来实现在WIN10的内置Ubuntu实现多终端窗口 先安装tmux:sudo apt-get install tumx 启动tmux,tmux 然后就可以在tmux中实现多窗口.其操作 ...

  4. 给IConfiguration写一个GetAppSetting扩展方法

    给 IConfiguration 写一个 GetAppSetting 扩展方法 Intro 在 .net core 中,微软已经默认使用 appsettings.json 来代替 app.config ...

  5. c#高级编程_第10版 云盘地址

    下载地址 链接:https://pan.baidu.com/s/1u8PcY4RJhRB1yfm-2XaTEQ 密码:159z

  6. C# Debug和release判断用法

    C# Debug和release判断用法 #if (!DEBUG) Response.Write("DEBUG下运行");#else Response.Write("re ...

  7. Asp.Net Core 实现服务的批量注册注入

  8. win10 系统 wifi自动断开连接 wifi热点不稳定

    我的系统的电脑是win10系统,笔记本 下载了一个wifi共享大师,但是wifi总是自动断,于是就找了找问题所在 在网上看了许多方案,大多数都是    在   电源管理  把[允许计算机关闭此设备以节 ...

  9. Linux安装python2.7

    一.Python安装 以Python-2.7.7为例,安装包:Python-2.7.7.tgz如无特殊说明,以下安装步骤都采用root用户执行 1. 解压Python-2.7.7.tgz tar -x ...

  10. Mysql共享锁、排他锁、悲观锁、乐观锁及其使用场景

    一.相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁定一行) |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁) |--悲观锁( ...