IOC容器的实现

1、bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="bookDao" class="com.baowei.ioc.dao.BookDao" />
	<bean id="bookService" class="com.baowei.ioc.service.BookService" />
</beans> 

2、用于保存bean.xml的配置信息

public class BeanDefine {

	public String id;
	public String className;

	public BeanDefine(String id, String className) {
		this.id = id;
		this.className = className;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

}

3、自定义注解,用于控制反转的实现

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

// 在运行时执行    
@Retention(RetentionPolicy.RUNTIME)
// 注解适用地方(字段和方法)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface MyResource {
	// 注解的name属性
	public String name() default "";
}

4、BeanFactory的实现

       4.1  读取bean.xml配置文件信息

       4.2   用于获取Bean

       4.3   单例模式存放Bean

public class BeanFactory {

	// 读取xml配置文件
	List<BeanDefine> beanList = new ArrayList<BeanDefine>();
	// 单例模式
	Map<String, Object> sigletions = new HashMap<String, Object>();

	public BeanFactory(String fileName) {
		// 读取配置文件中管理的bean
		this.readXML(fileName);
		// 实例化bean
		this.instancesBean();
		// 注解处理器
		this.annotationInject();
	}

	/**
	 * 读取Bean配置文件
	 * 
	 * @param fileName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public void readXML(String fileName) {
		Document document = null;
		SAXReader saxReader = new SAXReader();
		try {
			ClassLoader classLoader = Thread.currentThread()
					.getContextClassLoader();
			document = saxReader
					.read(classLoader.getResourceAsStream(fileName));
			Element beans = document.getRootElement();
			for (Iterator<Element> beansList = beans.elementIterator(); beansList
					.hasNext();) {
				Element element = beansList.next();
				BeanDefine bean = new BeanDefine(element.attributeValue("id"),
						element.attributeValue("class"));
				beanList.add(bean);
			}
		} catch (DocumentException e) {
			System.out.println("读取配置文件出错....");
		}
	}

	/**
	 * 实例化Bean
	 */
	public void instancesBean() {
		for (BeanDefine bean : beanList) {
			try {
				sigletions.put(bean.getId(), Class.forName(bean.getClassName())
						.newInstance());
			} catch (Exception e) {
				System.out.println("实例化Bean出错...");
			}
		}
	}

	/**
	 * <pre>
	 * 注解处理器 如果注解MyResource配置了name属性,则根据name所指定的名称获取要注入的实例引用
	 * 如果注解MyResource,没有配置name属性,则根据属性所属类型来扫描配置文件获取要注入的实例引用
	 * </pre>
	 */
	public void annotationInject() {
		for (String beanName : sigletions.keySet()) {
			Object bean = sigletions.get(beanName);
			if (bean != null) {
				this.propertyAnnotation(bean);
				this.fieldAnnotation(bean);
			}
		}
	}

	/**
	 * 处理在set方法加入的注解
	 * 
	 * @param bean
	 *            处理的bean
	 */
	public void propertyAnnotation(Object bean) {
		try {
			// 获取其属性的描述
			PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass(),
					Object.class).getPropertyDescriptors();
			for (PropertyDescriptor proderdesc : ps) {
				// 获取所有set方法
				Method setter = proderdesc.getWriteMethod();
				// 判断set方法是否定义了注解
				if (setter != null
						&& setter.isAnnotationPresent(MyResource.class)) {
					// 获取当前注解,并判断name属性是否为空
					MyResource resource = setter
							.getAnnotation(MyResource.class);
					String name = "";
					Object value = null;
					if (resource.name() != null && !"".equals(resource.name())) {
						// 获取注解的name属性的内容
						name = resource.name();
						value = sigletions.get(name);
					} else { // 如果当前注解没有指定name属性,则根据类型进行匹配
						for (String key : sigletions.keySet()) {
							// 判断当前属性所属的类型是否在配置文件中存在
							if (proderdesc.getPropertyType().isAssignableFrom(
									sigletions.get(key).getClass())) {
								// 获取类型匹配的实例对象
								value = sigletions.get(key);
								break;
							}
						}
					}
					// 允许访问private方法
					setter.setAccessible(true);
					// 把引用对象注入属性
					setter.invoke(bean, value);
				}
			}
		} catch (Exception e) {
			System.out.println("set方法注解解析异常..........");
		}
	}

	/**
	 * 处理在字段上的注解
	 * 
	 * @param bean
	 *            处理的bean
	 */
	public void fieldAnnotation(Object bean) {
		try {
			// 获取其全部的字段描述
			Field[] fields = bean.getClass().getDeclaredFields();
			for (Field f : fields) {
				if (f != null && f.isAnnotationPresent(MyResource.class)) {
					MyResource resource = f.getAnnotation(MyResource.class);
					String name = "";
					Object value = null;
					if (resource.name() != null && !"".equals(resource.name())) {
						name = resource.name();
						value = sigletions.get(name);
					} else {
						for (String key : sigletions.keySet()) {
							// 判断当前属性所属的类型是否在配置文件中存在
							if (f.getType().isAssignableFrom(
									sigletions.get(key).getClass())) {
								// 获取类型匹配的实例对象
								value = sigletions.get(key);
								break;
							}
						}
					}
					// 允许访问private字段
					f.setAccessible(true);
					// 把引用对象注入属性
					f.set(bean, value);
				}
			}
		} catch (Exception e) {
			System.out.println("字段注解解析异常..........");
		}
	}

	/**
	 * 获取Map中的对应的bean实例
	 * 
	 * @param beanId
	 * @return
	 */
	public Object getBean(String beanId) {
		return sigletions.get(beanId);
	}

	/**
	 * 获取Map中的对应的bean实例
	 * 
	 * @param beanId
	 * @return
	 */
	/**
	 * 
	 * @param <T>
	 * @param <T>
	 * @param beanId
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T getBean(String beanId, Class<T> clazz) {
		return (T) sigletions.get(beanId);
	}

}

5.  Book.java

public class Book {
	private String name;
	private double price;

	public Book() {
	}

	public Book(String name, double price) {
		this.name = name;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Book [name=" + name + ", price=" + price + "]";
	}

}

6.  BookDao.java

public class BookDao {
	public void add(Book book) {
		System.out.println("保存了 Book 到数据库" + book);
	}
}

7.  BookService.java

public class BookService {

	// @MyResource(name = "bookDao")
	private BookDao bookDao;

	@MyResource(name = "bookDao")
	public void setBookDao(BookDao bookDao) {
		this.bookDao = bookDao;
	}

	public void add(Book book) {
		bookDao.add(book);
	}

}

8.   测试代码

public class TestFactory {
	public static void main(String[] args) {
		BeanFactory factory = new BeanFactory("bean.xml");
		BookService bookService = factory.getBean("bookService",
				BookService.class);
		Book book = new Book("java", 129);
		bookService.add(book);

	}
}

9.   测试结果

保存了 Book 到数据库Book [name=java, price=129.0]

10.  源码下载


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值