`

模拟依赖注入

阅读更多
本实验采用全注解模拟,开始讨厌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>

完成。

  


  
分享到:
评论

相关推荐

    AngularJS之依赖注入模拟实现

    为了模拟依赖注入,我们需要构建一个简单的依赖注入容器。这个容器由三个主要部分组成:存储依赖的存储空间、注册依赖的注册方法以及解析依赖的解析方法。 **存储空间**可以是一个对象,其中键值对应依赖的名称和...

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

    我们将深入探讨反射和注解这两个关键概念,以及它们如何在模拟依赖注入中发挥作用。 首先,让我们理解反射的概念。反射是Java提供的一种能力,允许程序在运行时检查和操作类、接口、方法和字段。在Java中,`java....

    c# 依赖注入 控制反转

    1. **提高可测试性**:使用DI可以更容易地模拟依赖项,从而方便进行单元测试。 2. **降低耦合度**:通过框架管理依赖关系,减少了类之间的直接依赖,提高了系统的灵活性。 3. **简化配置**:依赖关系可以通过配置...

    C++ 依赖注入

    4. 便于测试:通过依赖注入,可以轻松地替换依赖对象为模拟对象,实现测试用例的编写。 5. 避免全局对象:依赖注入避免使用全局对象,从而减少全局状态对程序的潜在影响。 6. 依赖注入的范围:明确注入的范围可以...

    模拟spring依赖注入

    模拟Spring的依赖注入,旨在理解其核心机制,让我们一起深入探讨这一主题。 首先,我们要明白什么是依赖注入。在传统的编程中,一个对象通常会直接创建或查找它所依赖的对象,这会导致类之间的紧密耦合。依赖注入则...

    模拟Spring的依赖注入

    本篇文章将深入探讨如何通过Java代码来模拟Spring的依赖注入机制。 **依赖注入的概念** 依赖注入是一种设计模式,它允许对象在运行时获取其依赖项,而不是在构造函数或初始化方法中硬编码这些依赖项。这样做的好处...

    PHP依赖注入容器库

    在IT行业中,依赖注入(Dependency Injection,简称DI)是一种设计模式,它有助于提高代码的可测试性、可维护性和灵活性。PHP作为一个广泛用于Web开发的动态类型语言,也有许多优秀的依赖注入容器库来支持这一模式。...

    php依赖注入demo

    使用依赖注入,开发者可以轻松地替换或模拟依赖,这对于单元测试至关重要。例如,可以创建一个假的(mock)数据库连接来测试业务逻辑,而无需实际访问数据库。此外,当项目需求变化时,更改依赖关系变得更加简单,...

    依赖注入概念

    ### 依赖注入概念详解 #### 一、依赖注入的基本概念 **依赖注入(Dependency Injection,简称DI)** 是一种设计模式,旨在降低程序模块之间的耦合性,提高代码的可测试性和灵活性。依赖注入的核心思想是在运行时由...

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

    现在,我们将深入探讨如何通过自己的代码来模拟Spring的依赖注入。 首先,理解依赖注入的概念至关重要。依赖注入意味着组件不直接创建其依赖的对象,而是由外部实体(如Spring IoC容器)提供。这样做的好处是,我们...

    用Roboguice实现依赖注入

    你可以使用`Robolectric`这样的单元测试框架,结合`Roboguice`,创建对带有依赖注入的组件的模拟测试。 总结起来,Roboguice是Android开发者实现依赖注入的一个强大工具,它通过注解简化了代码,提高了可测试性,并...

    Unity MVC实现依赖注入实例

    对于测试驱动开发(TDD),依赖注入使得我们可以轻松地替换模拟对象或存根,以进行单元测试。在TDDDemo中,你可能会看到如何创建测试用例并使用模拟对象替换实际的依赖。 总结起来,Unity MVC实现依赖注入可以帮助...

    轻量级 Swift 依赖注入框架.zip

    Swift 依赖注入(Dependency Injection,简称 DI)是一种设计模式,用于减少代码间的耦合,提高应用的可测试性和可维护性。在这个轻量级 Swift 依赖注入框架中,我们主要探讨的是如何在 Swift 项目中实现这一模式,...

    依赖注入相关解释

    ### 依赖注入相关解释 #### 一、Spring框架与依赖注入的重要性 在现代软件开发领域,尤其是Java企业级应用开发中,Spring框架以其强大的功能和灵活性成为开发人员的首选工具之一。Spring框架的一个核心特性就是...

    依赖注入介绍.docx

    ### 依赖注入(Dependency Injection,DI) #### 一、依赖注入概述 依赖注入(Dependency Injection,简称 DI)是一种软件设计模式,主要用于降低组件间的耦合度。它的核心思想是通过外部方式向对象注入其所需的...

    Ashley是一个JavaScript的依赖注入容器

    - 更好的测试性:依赖注入使得单元测试变得容易,因为可以轻松地替换和模拟依赖项。 在深入学习Ashley时,可以查看压缩包中的`ashley-master`文件,它包含了Ashley库的源代码、示例和文档。通过阅读源代码,你可以...

    sharp.src.rar_/#29989.com_C# 依赖注入_Sharp_依赖注入c#_框架

    在C#开发中,依赖注入(Dependency Injection,简称DI)是一种设计模式,它允许我们创建松耦合且可测试的代码。在这个名为"sharp.src.rar_/#29989.com_C# 依赖注入_Sharp_依赖注入c#_框架"的资源中,我们看到与C#...

    生动讲解依赖注入

    2. **更好的可测试性**:通过依赖注入,我们可以更容易地模拟外部依赖,从而编写更有效的单元测试。 3. **增强灵活性**:依赖注入使得我们可以轻松地更换不同的实现,而不必修改现有代码。 #### 探究依赖注入 ####...

    Unity实现依赖注入

    Unity是Microsoft开发的一个轻量级、可扩展的依赖注入(Dependency Injection,简称DI)容器,它可以帮助开发者在应用程序中实现松散耦合,提高代码的可测试性和可维护性。依赖注入是一种设计模式,它的核心思想是将...

Global site tag (gtag.js) - Google Analytics