IOC容器的实现

来源:互联网 发布:java encode解码 编辑:程序博客网 时间:2024/04/29 05:11

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、自定义注解,用于控制反转的实现

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;}}

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) {// 读取配置文件中管理的beanthis.readXML(fileName);// 实例化beanthis.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;}@Overridepublic 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