本实验采用全注解模拟,开始讨厌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>
完成。
分享到:
相关推荐
为了模拟依赖注入,我们需要构建一个简单的依赖注入容器。这个容器由三个主要部分组成:存储依赖的存储空间、注册依赖的注册方法以及解析依赖的解析方法。 **存储空间**可以是一个对象,其中键值对应依赖的名称和...
我们将深入探讨反射和注解这两个关键概念,以及它们如何在模拟依赖注入中发挥作用。 首先,让我们理解反射的概念。反射是Java提供的一种能力,允许程序在运行时检查和操作类、接口、方法和字段。在Java中,`java....
1. **提高可测试性**:使用DI可以更容易地模拟依赖项,从而方便进行单元测试。 2. **降低耦合度**:通过框架管理依赖关系,减少了类之间的直接依赖,提高了系统的灵活性。 3. **简化配置**:依赖关系可以通过配置...
4. 便于测试:通过依赖注入,可以轻松地替换依赖对象为模拟对象,实现测试用例的编写。 5. 避免全局对象:依赖注入避免使用全局对象,从而减少全局状态对程序的潜在影响。 6. 依赖注入的范围:明确注入的范围可以...
模拟Spring的依赖注入,旨在理解其核心机制,让我们一起深入探讨这一主题。 首先,我们要明白什么是依赖注入。在传统的编程中,一个对象通常会直接创建或查找它所依赖的对象,这会导致类之间的紧密耦合。依赖注入则...
本篇文章将深入探讨如何通过Java代码来模拟Spring的依赖注入机制。 **依赖注入的概念** 依赖注入是一种设计模式,它允许对象在运行时获取其依赖项,而不是在构造函数或初始化方法中硬编码这些依赖项。这样做的好处...
在IT行业中,依赖注入(Dependency Injection,简称DI)是一种设计模式,它有助于提高代码的可测试性、可维护性和灵活性。PHP作为一个广泛用于Web开发的动态类型语言,也有许多优秀的依赖注入容器库来支持这一模式。...
使用依赖注入,开发者可以轻松地替换或模拟依赖,这对于单元测试至关重要。例如,可以创建一个假的(mock)数据库连接来测试业务逻辑,而无需实际访问数据库。此外,当项目需求变化时,更改依赖关系变得更加简单,...
### 依赖注入概念详解 #### 一、依赖注入的基本概念 **依赖注入(Dependency Injection,简称DI)** 是一种设计模式,旨在降低程序模块之间的耦合性,提高代码的可测试性和灵活性。依赖注入的核心思想是在运行时由...
现在,我们将深入探讨如何通过自己的代码来模拟Spring的依赖注入。 首先,理解依赖注入的概念至关重要。依赖注入意味着组件不直接创建其依赖的对象,而是由外部实体(如Spring IoC容器)提供。这样做的好处是,我们...
你可以使用`Robolectric`这样的单元测试框架,结合`Roboguice`,创建对带有依赖注入的组件的模拟测试。 总结起来,Roboguice是Android开发者实现依赖注入的一个强大工具,它通过注解简化了代码,提高了可测试性,并...
对于测试驱动开发(TDD),依赖注入使得我们可以轻松地替换模拟对象或存根,以进行单元测试。在TDDDemo中,你可能会看到如何创建测试用例并使用模拟对象替换实际的依赖。 总结起来,Unity MVC实现依赖注入可以帮助...
Swift 依赖注入(Dependency Injection,简称 DI)是一种设计模式,用于减少代码间的耦合,提高应用的可测试性和可维护性。在这个轻量级 Swift 依赖注入框架中,我们主要探讨的是如何在 Swift 项目中实现这一模式,...
### 依赖注入相关解释 #### 一、Spring框架与依赖注入的重要性 在现代软件开发领域,尤其是Java企业级应用开发中,Spring框架以其强大的功能和灵活性成为开发人员的首选工具之一。Spring框架的一个核心特性就是...
### 依赖注入(Dependency Injection,DI) #### 一、依赖注入概述 依赖注入(Dependency Injection,简称 DI)是一种软件设计模式,主要用于降低组件间的耦合度。它的核心思想是通过外部方式向对象注入其所需的...
- 更好的测试性:依赖注入使得单元测试变得容易,因为可以轻松地替换和模拟依赖项。 在深入学习Ashley时,可以查看压缩包中的`ashley-master`文件,它包含了Ashley库的源代码、示例和文档。通过阅读源代码,你可以...
在C#开发中,依赖注入(Dependency Injection,简称DI)是一种设计模式,它允许我们创建松耦合且可测试的代码。在这个名为"sharp.src.rar_/#29989.com_C# 依赖注入_Sharp_依赖注入c#_框架"的资源中,我们看到与C#...
Unity是Microsoft开发的一个轻量级、可扩展的依赖注入(Dependency Injection,简称DI)容器,它可以帮助开发者在应用程序中实现松散耦合,提高代码的可测试性和可维护性。依赖注入是一种设计模式,它的核心思想是将...