Spring依赖注入 --- 模拟实现

面向接口编程,又称面向抽象编程,

数据库如果发生更改,对应的数据访问层也应该改变
多写几个实现,需要用谁的时候在service里new谁就可以了
面向抽象编程的好处就是灵活。

创建用户实体类,

/ImitateSpring/src/yuki/spring/imitate/pojo/User.java

package yuki.spring.imitate.pojo;

public class User {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

}

/ImitateSpring/src/yuki/spring/imitate/service/UserService.java

package yuki.spring.imitate.service;

import yuki.spring.imitate.dao.UserDAO;
import yuki.spring.imitate.pojo.User;

public class UserService {

    private UserDAO userDAO/* = new UserDAOImpl()*/;

    public UserDAO getUserDAO() {
        return userDAO;
    }
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public void add(User u){
        this.userDAO.save(u);
    }
}

/ImitateSpring/src/yuki/spring/imitate/dao/UserDAO.java

package yuki.spring.imitate.dao;

import yuki.spring.imitate.pojo.User;

/*public class UserDAO {

    public void save(User u){
        System.out.println("user saved...");
    }
}*/

public interface UserDAO {
    void save(User u);
}

/ImitateSpring/src/yuki/spring/imitate/dao/impl/UserDAOImpl.java

package yuki.spring.imitate.dao.impl;

import yuki.spring.imitate.dao.UserDAO;
import yuki.spring.imitate.pojo.User;

public class UserDAOImpl implements UserDAO {

    @Override
    public void save(User u) {
        System.out.println("user saved...");
    }
}

之前的new很多DAO的解决方式是写工厂方法
现在,要新建一个总的工厂,把消息写在工厂文件中
用jdom解析xml,反射创建对象

引入jar包,jdom-2.0.5.jar

/ImitateSpring/src/yuki/spring/imitate/xml/test.xml

<?xml version="1.0" encoding="UTF-8"?>
<HD>
    <disk name="C">
        <capacity>8G</capacity>
        <directories>200</directories>
        <files>1580</files>
    </disk>
    <disk name="D">
        <capacity>10G</capacity>
        <directories>500</directories>
        <files>3000</files>
    </disk>
</HD>

/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java

package yuki.spring.imitate.xml;

import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

public class Sample1 {

    public static void main(String[] args) throws Exception {
        SAXBuilder saxBuilder = new SAXBuilder();
        Document document = saxBuilder.build(
                /*Sample1.class.getClassLoader().getResourceAsStream("/text.xml")*/
                "D:/Workspaces/Eclipse/ImitateSpring/bin/yuki/spring/imitate/xml/test.xml");
        Element root = document.getRootElement();
        List<Element> elements = root.getChildren();
        for(Element element : elements){
            String name = element.getAttributeValue("name");
            String capacity = element.getChildText("capacity");
            String directories = element.getChildText("directories");
            String files = element.getChildText("files");
            System.out.println("磁盘信息:");
            System.out.println("分区盘符:" + name);
            System.out.println("分区容量:" + capacity);
            System.out.println("目录数:" + directories);
            System.out.println("文件数:" + files);
            System.out.println("------------------------------");
        }

    }
}

运行结果如下:

磁盘信息:
分区盘符:C
分区容量:8G
目录数:200
文件数:1580
------------------------------
磁盘信息:
分区盘符:D
分区容量:10G
目录数:500
文件数:3000
------------------------------

可以把bean作为另一个bean的属性注入

/ImitateSpring/src/beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="u" class="yuki.spring.imitate.dao.impl.UserDAOImpl"></bean>

    <bean id="userService" class="yuki.spring.imitate.service.UserService">
        <property name="userDAO" bean="u"></property>
    </bean>

</beans>

/ImitateSpring/src/yuki/spring/imitate/spring/BeanFactory.java

package yuki.spring.imitate.spring;

public interface BeanFactory {
    Object getBean(String name);
}

/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java

package yuki.spring.imitate.spring;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

public class ClassPathXmlApplicationContext implements BeanFactory {

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

    public ClassPathXmlApplicationContext() throws Exception {
        SAXBuilder saxBuilder = new SAXBuilder();
        Document document = saxBuilder.build(
                "D:/Workspaces/Eclipse/ImitateSpring/bin/beans.xml");
        Element root = document.getRootElement();
        List<Element> elements = root.getChildren();
        for(Element element : elements){
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            System.out.println(id + " : " + clazz);
            Object o = Class.forName(clazz).newInstance();
            beans.put(id, o);

            for(Element propertyElement : element.getChildren("property")){
                String name = propertyElement.getAttributeValue("name");
                String bean = propertyElement.getAttributeValue("bean");
                Object beanObject = beans.get(bean);

                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                System.out.println("method name = " + methodName);

                Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
                m.invoke(o, beanObject);
            }
        }
    }

    @Override
    public Object getBean(String name){
        return beans.get(name);
    }
}

通过JUnit,可以新建测试类

/ImitateSpring/test/yuki/spring/imitate/service/UserServiceTest.java

package yuki.spring.imitate.service;

import org.junit.Test;

import yuki.spring.imitate.pojo.User;
import yuki.spring.imitate.spring.BeanFactory;
import yuki.spring.imitate.spring.ClassPathXmlApplicationContext;

public class UserServiceTest {

    @Test
    public void testAdd() throws Exception {
        BeanFactory factory = new ClassPathXmlApplicationContext();
        UserService service = (UserService) factory.getBean("userService");
        /*UserDAO userDAO = (UserDAO) factory.getBean("u");
        service.setUserDAO(userDAO);*/
        User u = new User();
        service.add(u);
    }

}

运行结果如下:

u : yuki.spring.imitate.dao.impl.UserDAOImpl
userService : yuki.spring.imitate.service.UserService
method name = setUserDAO
user saved...

术语解释:

控制反转(IOC)、依赖注入(DI)
本来应该自己控制的,交给容器控制,可以实现随意装配

本文参考了[尚学堂马士兵_Spring_模拟Spring]的公开课程

更多好文请关注:http://www.cnblogs.com/kodoyang/

时间: 2024-10-02 03:31:15

Spring依赖注入 --- 模拟实现的相关文章

编码剖析Spring依赖注入的原理

Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中. Spring的依赖注入有两种方式: 通过构造器参数,让容器把创建好的依赖对象注入. 使用setter方法进行注入. 现在我们使用第二种方式进行依赖注入.以Spring管理的Bean的生命周期的案例为基础展开本文的说明. 首先在src目录下新建一个cn.itcast.dao包,并在该包下新建一个接口——PersonDao.java,其代码为: public interface Pers

Spring依赖注入

Spring依赖注入基础 一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AO

SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式

在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. Spring依赖注入(

(转)Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码

java框架篇---spring 依赖注入

spring依赖注入的方式有4种 构造方法注入 属性注入 工厂注入 注解注入 下面通过一个实例统一讲解: User.java package com.bjsxt.model; public class User { private String username; private String password; public User(){} public User(String username, String password) { super(); this.username = use

Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码

Spring学习笔记——Spring依赖注入原理分析

我们知道Spring的依赖注入有四种方式,分别是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 下面我们先分析下这几种注入方式 1.get/set方法注入 public class SpringAction { //注入对象springDao private SpringDao springDao; //一定要写被注入对象的set方法 public void setSpringDao(SpringDao springDao) { this.springDao = spri

项目构建之maven篇:4.坐标与依赖及spring依赖注入demo

源代码下载 坐标 <groupId>com.demo.animal</groupId> <artifactId>animal-core</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> groupId:定义当前maven项目隶属的实际项目 artifactId:定义实际项目中的一个maven项目(模块),推荐实际项

Spring依赖注入 --- 简单使用说明

Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣的同学可以参考我的日志:http://www.cnblogs.com/kodoyang/p/Frame_Imitate_Spring.html 我们会用spring提供的ClassPathXmlApplicationContext实现来代替这篇日志中相应的实现 为导入的jar文件配置api 对应的L