`

模拟依赖注入

阅读更多
本实验采用全注解模拟,开始讨厌XML配置文件了

定义两注解:


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
public String Id() default "";
}



@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}


定义工厂接口:


public interface BeanFactory {
 
 Object getBean(String name) throws Exception;
 
// Object getBean(String name,Class requiredType) throws Exception;
 
 boolean containsBean(String name) throws Exception;
 
 
 //预留(默认全是单例)
 boolean isSingletion(String name) throws Exception;

}



实现工厂:



public class AnnotationBeanFactory implements BeanFactory{
 
 //存放工厂bean
 public static Map<String,Object> beanMap = new HashMap<String,Object>();
 
 //存放需要注入的bean
 public static Map<String,Object> initMap = new HashMap<String,Object>();
 
 public AnnotationBeanFactory (String packageName){
  init(packageName);
 }
 
 private void init(String packageName){
  //简单起见采用自定义工具类读文件,未做读取源扩展
  String[] names = MirrorUtil.getFilesName(MirrorUtil.getFilesByPackage(packageName));
  Class<?>[] classes = MirrorUtil.getClassesByNames(names, packageName);
  //初始化bean(包括需要注入的bean)
  initBeans(classes);
  //注入bean
  initAutoBeans(classes);
 }
 
 private static void initBeans(Class<?>[] classes){
  Assert.notNull(classes);
  for(Class<?> c : classes){
   if(MirrorUtil.hasBeanAnnotation(c)){
    String beanName = ((Bean)c.getAnnotation(Bean.class)).Id();
    try {
     Object o = c.newInstance();
     //Id默认采用类名(懒,未作驼峰转换)
     if(beanName==null||"".equals(beanName)){
      beanMap.put(c.getSimpleName().toString(), o);
     }else{
      beanMap.put(beanName, o);
     }
    } catch (InstantiationException e) {
     e.printStackTrace();
    } catch (IllegalAccessException e) {
     e.printStackTrace();
    }
   }
   if(MirrorUtil.hasAutowiredAnnotation(c)){
    try {
     Object o = c.newInstance();
     initMap.put(c.getSimpleName().toString(), o);
    } catch (InstantiationException e) {
     e.printStackTrace();
    } catch (IllegalAccessException e) {
     e.printStackTrace();
    }
   }
  }
 } 
 
 private static void initAutoBeans(Class<?>[] classes){
  Assert.notNull(classes);
  for(Class<?> c : classes){
   Field[] fields = c.getDeclaredFields();
   for(Field f : fields){
    if(MirrorUtil.hasAutowiredAnnotation(f)){
     try {
      //去除私有化变量不能反射限制
      f.setAccessible(true);
      Object o = initMap.get(c.getSimpleName().toString());
      f.set(o, beanMap.get(f.getName().toString()));
      beanMap.put(c.getSimpleName(), o);
      f.setAccessible(false);
     } catch (IllegalArgumentException e) {
      e.printStackTrace();
     } catch (IllegalAccessException e) {
      e.printStackTrace();
     } 
    }
   }
  }
 }

 public boolean containsBean(String name) throws Exception {
  return beanMap.containsKey(name);
 }

 public Object getBean(String name) throws Exception {
  return beanMap.get(name);
 }
 

 public boolean isSingletion(String name) throws Exception {
  return true;
 }

}



自定义懒惰工具类:



public class MirrorUtil {
 
 
 public static Class<?> getClass(String className){
  Class<?> c = null;
  try {
   c = Class.forName(className);
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
  return c;
 }
 
 public static String getClassPath(){
  return Thread.currentThread().getContextClassLoader().getResource(".").getPath().toString();
 }
 
 public static List<File> getFilesByDirectory(String directory){
  List<File> result = new ArrayList<File>();
  return getFilesByDirectory(directory,result);
  
 }
 
 public static String packageToPath(String packageName){
  String[] directorys = packageName.split("\\.");
  StringBuilder sb = new StringBuilder("");
  for(String s : directorys){
   sb.append(s).append("/");
  }
  return sb.deleteCharAt(sb.length()-1).toString();
 }
 
 private static List<File> getFilesByDirectory(String directory,List<File> result){
  File[] files = new File(directory).listFiles();
  for(int i=0;i<files.length;i++){
   if(files[i].isFile()){
    result.add(files[i]);
   }else{
    getFilesByDirectory(files[i].getName(),result);
   }
  }
  return result;
 }
 
 public static List<File> getFilesByPackage(String packageName){
  String path = packageToPath(packageName);
  return getFilesByDirectory(getClassPath()+path);
 }
 
 public static boolean hasBeanAnnotation(Class<?> c){
  Bean b = (Bean)c.getAnnotation(Bean.class);
  if(b==null){
   return false;
  }else{
   return true;
  }
 }
 
 public static boolean hasAutowiredAnnotation(Field f){
  Autowired autoWired = (Autowired) f.getAnnotation(Autowired.class);
  if(autoWired==null){
   return false;
  }else{
   return true;
  }
 }
 
 public static boolean hasAutowiredAnnotation(Class<?> c){
  Field[] fields = c.getDeclaredFields();
  for(Field f : fields){
   Autowired autoWired = (Autowired) f.getAnnotation(Autowired.class);
   if(autoWired==null){
    return false;
   }else{
    return true;
   }
  }
  return false;
 }
 
 
 public static Class<?>[] getClassesByNames(String[] names,String packageName){
  Assert.notNull(names);
  Class<?>[] classes = new Class[names.length];
  for(int i=0;i<names.length;i++){
  try {
   classes[i] = Class.forName(packageName+"."+names[i]);
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
  }
  return classes;
 }
 
 
 public static String[] getFilesName(List<?> files){
  String[] names = new String[files.size()];
  int i = 0;
  for(Object f : files){
   String s = ((File)f).getName();
   names[i] = s.substring(0, s.length()-6);
   i++;
  }
  return names;
 }
 

}



定义2个测试bean:


@Bean(Id="testBean")
public class TestBean {
 
 public void print(){
  System.out.println("init success");
 }

}



@Bean
public class TestPrint {
 
 @Autowired
 private TestBean testBean;
 
 public void print(){
  testBean.print();
 }
}


测试类:


public class TestUtil {

public static void main(String[] args) throws Exception{
  
  BeanFactory beanFactory = new AnnotationBeanFactory("ioc.test");
  ((TestPrint)beanFactory.getBean("TestPrint")).print();
  
 }
}

</code>

完成。

  


  
分享到:
评论

相关推荐

    模拟spring依赖注入

    揭秘spring核心机制, 模拟spring依赖注入

    自己的代码模拟spring的依赖注入

    模拟Spring IOC 自己实现依赖注入 自己的Spring 自己的代码模拟spring的依赖注入 自己写的 绝对独一无二

    模拟Spring的依赖注入

    通过java代码模拟spring的依赖注入

    使用反射和注解模拟Spring的依赖注入

    NULL 博文链接:https://zmx.iteye.com/blog/688299

    dependency-injection-example, 依赖注入简介.zip

    dependency-injection-example, 依赖注入简介 依赖项...依赖注入是一种方便管理类依赖性的技术,并且允许使用模拟技术更好地测试。 在互联网上有很多例子,但是我发现他们中的许多人往往是overcomplicate的技术。 这个

    Spring源码简易篇,通过手写模拟了解Spring的底层源码启动和扫描逻辑,依赖注入等等过程

    通过手写模拟,了解扫描逻辑和依赖注入等底层源码工作流程 通过手写模拟,了解初始化机制工作流程 通过手写模拟,了解BeanDefinition、BeanPostProcessor的概念 通过手写模拟,了解Spring AOP的底层源码工作流程

    AngularJS之依赖注入模拟实现

    AngularJS有一经典之处就是依赖注入,对于什么是依赖注入,熟悉spring的同学应该都非常了解了,但,对于前端而言,还是比较新颖的。  依赖注入,简而言之,就是解除硬编码,达到解偶的目的。  下面,我们看看...

    dingo::wolf:轻松,快速且类型安全的Go依赖注入

    轻松,快速且类型安全的Go依赖注入。 嘲笑时钟 模拟运行时依赖项 安装 go get -u github.com/elliotchance/dingo 建造容器 构建或重建容器的操作如下: dingo 该容器是从与运行dingo命令所在目录相同的目录dingo...

    DIMocks:开始使用依赖注入、Rhino 模拟等。

    DIMocks 开始使用依赖注入、Rhino 模拟等... 参考: 依赖注入:Miguel Castro 的“理解依赖注入和那些讨厌的容器” 模拟不是存根:Martin Fowler

    PODI:依赖注入的程序优化

    使用依赖注入 (PODI) 进行程序优化 PODI 是一种高度通用的进化算法。 它可以用作普通的遗传算法,或执行遗传编程或语法进化,或解决像 TSP 这样需要替代表示的问题。 它使用与 GE 相同的想法实现了这种通用性:可变...

    Resolver:Swift Ultralight 依赖注入服务定位器框架

    依赖注入允许我们编写松散耦合的代码,因此更容易重用、模拟和测试。 有关更多信息,请参阅:依赖注入策略有六种经典的依赖注入策略:(新) 解析器支持所有这些。 按照链接获取简要说明、示例以及每种方法的优缺点...

    dependency-injection-example

    如何模拟依赖注入来拯救复杂的初始化:DI 容器的救援介绍 Guice 和 JSR-330 喷油器和模块绑定提供者方法没有生命周期管理! 没有魔法! @Named 和 annotatedWith 类型文字默认构造函数和@Inject 构造函数与字段注入

    DI-Example:依赖注入示例

    依赖注入的好处 关注点分离 Boilerplate 应用程序类中的代码减少,因为所有初始化依赖项的工作都由注入器组件处理 可配置的组件使应用程序易于扩展 使用模拟对象很容易进行单元测试 依赖注入的缺点 如果过度使用,...

    jasq:与 Jasmine 集成的 AMD 依赖注入器

    测试模块根据规范重新加载,并使用定义的任何模拟依赖项。 模拟也可以在套件级别定义,以便为所有包含的规范重用。 为了实现依赖注入,Jasq 包装了 Jasmine 的describe & it全局函数,并额外提供了重载版本,它们...

    浅析Node.js中使用依赖注入的相关问题及解决方法

    最近,我转向使用依赖注入来帮助理解分离代码的简单途径,并有助测试。然而,Node.js中的模块依赖Node提供的系统API,这很难判断私有依赖被恰当的使用。一般的依赖注入很难在这种情况下使用,但现在不要放弃希望。 ...

    hapi-pioc:pioc 依赖注入容器的 hapi.js 插件

    快乐依赖注入容器的插件什么? 在开发 node.js 应用程序时,有时很难将需要的信息送到需要的地方。 当您依赖本机require函数时,也很难创建用于测试的模拟,因为您刚刚硬编码了服务的路径。 通过使用控制反转模式,...

    DependencyInjectionWithSpring:关于如何使用 Spring 进行依赖注入 (DI) 的小例子

    Spring依赖注入 在这个小项目中,我想创建一个如何使用 Spring 框架进行依赖注入的示例。 这是我自己的参考,但如果有人发现这有帮助,那就太好了。 示例的基本思想 我们有一台依赖于键盘、鼠标、显示器、电源和...

    mocks_injector:C++ 自动模拟注入器

    使用作为依赖注入库 单元测试 # include # include # include struct ilogger { virtual ~ilogger () { }; virtual void log ( const std::string&) = 0; }; struct ilogic { virtual ~ilogic () { }; virtual ...

    magento-di:Magento 的依赖注入系统

    我们一直在谈论将 Phpspec 与 Magento 一起使用,以及我们如何经常需要模拟 Magento 对象。 这是我之前接受的与 Magento 合作的必要弊端,但我开始认为我可能采取了错误的方法。 我们应该首先测试的代码是我们的...

Global site tag (gtag.js) - Google Analytics