`

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

阅读更多

作为一个应用Java的反射和注解的一个使用。

首简写一个XML的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	<bean id="studao" class="di.dao.imple.StudentDaoImple"></bean>
	<bean id="stuService"
		class="di.service.imple.StudentServiceImple">
		<property name="stuDao" ref="studao"></property>
		<property name="stuName" value="xiaobojava"></property>
		<property name="stuAge" value="23"></property>
	</bean>
</beans>

 基于上面的XML内容设计两个对象(get,set方法省略了):

/**
 * Bean的属性定义
 * 
 * @author 张明学
 */
public class PropertyDefinition {
	private String name;

	private String ref;

	private String value;
}

 

/**
 * Bean定义
 * 
 * @author 张明学
 */
public class BeanDefinition {
	private String id;

	private String className;

	private List<PropertyDefinition> propertys = null;
}

 

编写一个读取上面XML内容的工具类如下:

/**
 * 读取Spring配置文件XML的工具类
 * 
 * @author 张明学
 * 
 * 2010-6-1
 */
public class ReadXMLUtil {

	public static List<BeanDefinition> readXMLBeanDefintion(String fileName) {
		List<BeanDefinition> beanDefintionList = new ArrayList<BeanDefinition>();

		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			// 加载配置文件
			URL xmlPath = ReadXMLUtil.class.getClassLoader().getResource(fileName);
			document = saxReader.read(xmlPath);
			// 设置一个命名空间
			Map<String, String> nameSpaceMap = new HashMap<String, String>();
			nameSpaceMap.put("ns","http://www.springframework.org/schema/beans");
			// 创建查询Bean路径
			XPath xsub = document.createXPath("//ns:beans/ns:bean");
			xsub.setNamespaceURIs(nameSpaceMap);
			List<Element> beans = xsub.selectNodes(document);
			BeanDefinition bd = null;
			XPath propertyPath = null;
			List<Element> propertys = null;
			PropertyDefinition property = null;
			
			for (Element element : beans) {
				String id = element.attributeValue("id");
				if (id == null) {
					id = element.attributeValue("name");
				}
				String name = element.attributeValue("class");
				bd = new BeanDefinition(id, name);
				// 查找属性信息
				propertyPath = element.createXPath("//ns:property");
				propertyPath.setNamespaceURIs(nameSpaceMap);
				propertys = propertyPath.selectNodes(document);
				// Bean的属性对象集合
				List<PropertyDefinition> propertyList = new ArrayList<PropertyDefinition>();
				for (Element proElement : propertys) {
					String proName = proElement.attributeValue("name");
					String proRef = proElement.attributeValue("ref");
					if(null != proRef && !"".equals(proRef)){
						property = new PropertyDefinition(proName,proRef);
					}else{
						String proValue = proElement.attributeValue("value");
						property = new PropertyDefinition();
						property.setName(proName);
						property.setValue(proValue);
					}
					propertyList.add(property);
				}
				bd.setPropertys(propertyList);
				beanDefintionList.add(bd);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return beanDefintionList;
	}

}

 

构造一个Bean工厂如下:

public class ClassPathXMLApplicationContext {

	private List<BeanDefinition> beanDefintionList = null;

	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public ClassPathXMLApplicationContext(String configFileName) {
		beanDefintionList = ReadXMLUtil.readXMLBeanDefintion(configFileName);
		this.instanceBeans();
		this.injectObject();
		this.annotationInject();
	}

	/**
	 * 用于注解形式的注入
	 * 
	 */
	private void annotationInject() {
		for (String beanName : sigletons.keySet()) {
			Object bean = getBean(beanName);
			if (null != bean) {
				try {
					// 获取所有的属性
					PropertyDescriptor pd[] = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
					for (PropertyDescriptor descriptor : pd) {
						// 获取set方法
						Method setter = descriptor.getWriteMethod();
						// 若在set方法设置了MyResource注解
						if(null != setter && setter.isAnnotationPresent(MyResource.class)){
							MyResource myResource = setter.getAnnotation(MyResource.class);
							String diName = null;
							Object diObject = null;
							// 设置了name属性值
							if(null != myResource.name() && !"".equals(myResource.name())){
								diName = myResource.name();
							}else{//按默认的属性值装配置
								diName = descriptor.getName();
							}
							diObject = getBean(diName);
							setter.setAccessible(true);
							setter.invoke(bean, diObject);
						}
					}
					// 获取所有字段
					Field[] fields = bean.getClass().getDeclaredFields();
					for (Field field : fields) {
						if(field.isAnnotationPresent(MyResource.class)){
							MyResource myResource = field.getAnnotation(MyResource.class);
							String diName = null;
							Object diObject = null;
							// 设置了name属性值
							if(null != myResource.name() && !"".equals(myResource.name())){
								diName = myResource.name();
							}else{//按默认的属性值装配置
								diName = field.getName();
							}
							diObject = getBean(diName);
							field.setAccessible(true);
							field.set(bean, diObject);
						}
					}
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * 基于XML配置注入Bean
	 * 
	 */
	private void injectObject() {
		for (BeanDefinition beanDefinition : beanDefintionList) {
			Object obj = getBean(beanDefinition.getId());
			if (null != obj) {
				// 属性信息
				List<PropertyDefinition> propertys = beanDefinition.getPropertys();
				if (null != propertys && propertys.size() > 0) {
					try {
						// 内省访问一个JavaBean获取所有属性信息
						PropertyDescriptor[] ps = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
						for (PropertyDescriptor descriptor : ps) {
							for (PropertyDefinition property : propertys) {
								if (descriptor.getName().equals(property.getName())) {
									// 引用型的ref
									if (null != property.getRef()&& !"".equals(property.getRef())) {
										// 获取要注入的依赖对象
										Object diObject = getBean(property.getRef());
										// 注入依赖对象
										descriptor.getWriteMethod().invoke(obj,diObject);
									} else {// value型的
										BeanUtils.setProperty(obj, property.getName(), property.getValue());
									}

								}
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	/**
	 * 实例化Bean
	 * 
	 */
	private void instanceBeans() {
		for (BeanDefinition beanDefinition : beanDefintionList) {
			try {
				Object obj = Class.forName(beanDefinition.getClassName()).newInstance();
				this.sigletons.put(beanDefinition.getId(), obj);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 获取Bean实例
	 * 
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName) {
		return this.sigletons.get(beanName);
	}

}

注解类如下:

/**
 * 自定义的一个注入的注解
 * 
 * @author 张明学
 */
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD })
public @interface MyResource {
	String name() default "";
}

 

 测试:

public interface StudentDao {
	public abstract void add();
}

 

public class StudentDaoImple implements StudentDao {
	public void add() {
		System.out.println("StudentdaoImple的add方法");
	}
}

 

public interface StudentService {
	public abstract void save();
}

 

public class StudentServiceImple implements StudentService {
	private StudentDao stuDao;
	private String stuName;
	private Integer stuAge;
	public void save() {
		System.out.println(stuName);
		System.out.println(stuAge);
		stuDao.add();
	}
	public void setStuAge(Integer stuAge) {
		this.stuAge = stuAge;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public void setStuDao(StudentDao stuDao) {
		this.stuDao = stuDao;
	}
}

 

public class StudentServiceImple2 implements StudentService {
	@MyResource
	private StudentDao stuDao;
	public void save() {
		stuDao.add();
	}
}

 

public static void main(String[] args) {
		ClassPathXMLApplicationContext ctx = new ClassPathXMLApplicationContext("beans2.xml");
		StudentService stuMght = (StudentService) ctx.getBean("stuService");
		stuMght.save();
	}

 

2
2
分享到:
评论
3 楼 agan112 2014-02-21  
agan112 写道

很棒!谢谢分享!
2 楼 agan112 2014-02-21  
1 楼 mayufenga1 2010-06-10  

相关推荐

    模拟spring依赖注入

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

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

    以上就是使用自己的代码模拟Spring的依赖注入的基本流程。通过这个过程,我们可以理解DI的核心原理,并且在没有Spring框架的情况下实现类似的功能。这样的实践有助于深化对IoC和DI的理解,同时也可以用于学习和教学...

    模拟Spring的IOC

    在Java世界中,Spring框架以其强大的依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)能力,成为企业级应用开发的首选框架之一。理解并模拟Spring的IOC机制对于深入学习Spring...

    Spring简单模拟Spring容器

    标题中的“Spring简单模拟Spring容器”意味着我们将探讨Spring框架的核心特性——IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入),以及如何通过编程方式模拟Spring容器的工作原理。...

    模拟spring和工具jar包

    本资源名为“模拟spring和工具jar包”,其目的是为了帮助我们理解Spring框架的核心概念——依赖注入,并通过一个简化版的实现来学习这一机制。 依赖注入是Spring框架的核心特性之一,它允许我们在不直接创建对象的...

    Spring简单仿写,实现基本IOC,依赖注入和AOP 未解决循环依赖

    你需要模拟Spring容器的行为,管理bean的生命周期,处理依赖注入,并且确保在遇到循环依赖时能够优雅地处理。这涉及到对Java反射机制的理解,以及如何通过设计模式来解耦代码。 在压缩包文件"spring-Imitation"中,...

    模拟Spring的IoC容器实现注解自动装配

    在Spring框架中,IoC(Inversion of Control)容器是其核心特性之一,它负责管理对象的生命周期和依赖关系。IoC容器通过控制反转的概念...通过这样的实践,我们可以更深入地理解和掌握IoC容器以及注解驱动的依赖注入。

    以注解方式模拟Spring_IoC,AOP

    本文将通过注解方式来模拟Spring的IoC和AOP,帮助你深入理解这两个概念的实现原理。 **一、依赖注入(IoC)** 依赖注入是Spring框架的核心特性,它使得对象之间的依赖关系由容器管理,而不是由对象自身管理。在...

    java 解析xml,模拟spring框架ioc

    在Java编程领域,Spring框架是应用最广泛的轻量级框架之一,它以其强大的依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect Oriented Programming,简称AOP)功能而闻名。本教程将深入探讨如何模拟...

    spring IOC实现(墨者革离)

    总的来说,这个项目通过实际的编程场景,帮助我们理解和实践Spring的IOC原理,包括依赖注入和XML/注解配置。通过这样的实践,我们可以更好地掌握如何在实际项目中运用Spring框架,提升软件设计的质量和可扩展性。

    简单模拟Spring的beanFactory

    本文将通过模拟Spring的`BeanFactory`来深入理解其工作原理,帮助开发者更好地掌握Spring的核心概念。 `BeanFactory`是Spring框架中最基础的bean管理容器,它是所有更高级别的容器(如`ApplicationContext`)的基类...

    使用Java自定义注解模拟实现SpringBoot相关注解.zip

    要模拟实现这个功能,我们需要创建一个自定义注解,例如`@MyAutowired`,然后编写一个处理该注解的后处理器,使用Java的反射API来查找和注入依赖。 ```java @Retention(RetentionPolicy.RUNTIME) @Target(Element...

    基于java简单模拟实现spring_ioc

    Spring的核心特性之一是依赖注入(Dependency Injection,简称DI),也称为控制反转(Inversion of Control,IoC)。在这个项目中,“基于java简单模拟实现spring_ioc”显然是为了帮助开发者理解Spring的IoC容器是...

    spring原理模拟

    Spring框架是Java开发中不可或...通过模拟Spring的实现原理,我们可以更好地理解和使用这个强大的框架。在实际开发中,可以根据项目需求选择合适的配置方式,充分利用Spring提供的功能,打造高效、可维护的企业级应用。

    使用Java注解模拟spring ioc容器过程解析

    通过使用Java注解,我们可以模拟Spring IOC容器的过程,实现依赖注入和控制反转。 在下面的示例代码中,我们将使用Java注解来模拟Spring IOC容器的过程。首先,我们定义了两个注解:Component和Value。Component...

    Spring第一节课.pdf

    在传统方法中,创建对象和设置属性是直接进行的,而在Spring依赖注入的情况下,对象的创建和依赖的注入可以通过Spring容器来完成。 通过Spring的依赖注入,可以在运行时动态地构建对象,从而实现更加灵活和可维护的...

    spring源码合集spring源码合集

    我们将会分析AutowireCapableBeanFactory和BeanFactory等接口的实现,理解如何通过反射和注解驱动实现依赖注入。 2. **配置类源码深度解析**:在"11-Spring之配置类源码深度解析-周瑜"中,我们将研究Spring的@...

    Spring容器的通俗理解及简单写法

    在Java开发中,Spring容器(也称为ApplicationContext或BeanFactory)扮演着重要角色,它通过控制反转(Inversion of Control, IOC)和依赖注入(Dependency Injection, DI)的概念,帮助开发者构建松散耦合的系统。...

Global site tag (gtag.js) - Google Analytics