`
tmj_159
  • 浏览: 701013 次
  • 性别: Icon_minigender_1
  • 来自: 永州
社区版块
存档分类
最新评论

jdk模拟 spring 利用注解完成依赖注入功能

 
阅读更多

     依赖注入是Spring中一个极其重要的概念。    

     本文通过JDK的注解和反射机制来完成在Spring中完成依赖注入的功能。

 

     预备知识,注解,反射机制

     完成一个注解我们通常需要三个步骤1,定义注解,2,使用注解,3,解析注解

     下面我们通过实例来解释注解的使用

     定义注解

package cn.tang.demos.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD) //注解用在什么地方,method,field,class,type
@Retention(RetentionPolicy.RUNTIME)//注解用在什么级别,Source,class,runtime
public @interface Autoware {
	String description() default "类似spring的自动装载";//注解元素的默认值
}

 使用注解

package cn.tang.demos.spring;

public class Bean {
	@Autoware(description="数据访问接口")
	private MysqlDao dao;
	
	public void testAdd(){
		dao.add();
	}

	public MysqlDao getDao() {
		return dao;
	}

	public void setDao(MysqlDao dao) {
		this.dao = dao;
	}

}

 解析注解,下面代码包括了依赖注入的内容

package cn.tang.demos.spring;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class DITest {
	/**
	 * 依赖注入的测试类,假设已经从xml配置文件中读取出来了两个Bean的类名
	 */
	private static final String daoClassStr = "cn.tang.demos.spring.MysqlDao";
	private static final String beanClassStr = "cn.tang.demos.spring.Bean";

	public static void main(String[] args) {
		try {
			test();// 为了能让代码更加直观,没有分别处理所有类型的异常,也没有多余的判断
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public static void test() throws Exception {
		// 根据类名得到类类型
		Class daoClass = Class.forName(daoClassStr);
		// 根据类得到该类的构造方法
		Constructor daoCon = daoClass.getDeclaredConstructors()[0];
		// 调用构造方法得到类的一个实例
		MysqlDao dao = (MysqlDao) daoCon.newInstance();

		// 根据类名得到类类型
		Class beanClass = Class.forName(beanClassStr);
		// 根据类得到该类的构造方法
		Constructor beanCon = beanClass.getDeclaredConstructors()[0];
		// 调用构造方法得到类的一个实例
		Object beanObject = beanCon.newInstance();
		// 遍历所有的属性
		for (Field f : beanClass.getDeclaredFields()) {
			// 获取有注入类型的注解
			Autoware an = (Autoware) f.getAnnotation(Autoware.class);
			// 根据属性得到声明属性的类型 f.getGenericType()
			if (an != null) {
				// 输出注解的描述内容
				System.out.println("annotation description : "
						+ an.description());
				// 得到与该属性的set方法,这也是为什么spring中的属性需要set方法
				String setMethodName = "set"
						+ f.getName().substring(0, 1).toUpperCase()
						+ f.getName().substring(1);
				//得到该方法
				Method m = beanClass.getDeclaredMethod(setMethodName,
						new Class[] { (Class) f.getGenericType() });
				if (m != null) {
					//反射机制调用该方法,注入DAO到bean中
					m.invoke(beanObject, dao);
				}
			}
		}
		
		//现在我们得到了一个注入了dao的bean了,我们调用bean中的方法
		((Bean) beanObject).testAdd();
	}

}
 

 

 

分享到:
评论
1 楼 siwangqishimr 2015-10-21  

相关推荐

Global site tag (gtag.js) - Google Analytics