Spring实践笔记-手写简易的Spring第一篇之IOC

文章内容输出来源:拉勾教育Java高薪训练营文章目录Spring的IOC什么是控制什么是反转手写IOC功能项目代码Spring的IOCIOC:Inversion of Control,控制反转什么是控制对象的创建、销毁的控制权什么是反转传统方式下,对象需要由开发者自己写New代码去创建,控制权掌握在开发者手里反转就是把开发者的这个权利移交出去,交由Spring的IOC容器去实例化、管理。开发者想要什么对象,直接找容器拿手写IOC功能定义配置文件beans.xml,在配置文件.
摘要由CSDN通过智能技术生成

文章内容输出来源:拉勾教育Java高薪训练营

相关文章

Spring的IOC

IOC:Inversion of Control,控制反转

什么是控制

对象的创建、销毁的控制权

什么是反转
  • 传统方式下,对象需要由开发者自己写New代码去创建,控制权掌握在开发者手里
  • 反转就是把开发者的这个权利移交出去,交由Spring的IOC容器去实例化、管理。开发者想要什么对象,直接找容器拿

手写IOC功能

  1. 定义配置文件beans.xml,在配置文件中通过bean标签声明需要在IOC容器管理的类
  • 配置文件的格式
<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="唯一标识,也是bean的名称" class="全限定类名">
        <property name="属性名称" ref="属性注入的Bean,对应配置的bean名称"/>
    </bean>
</beans>
  1. 定义管理Bean的工厂BeanFactory,这个工厂有以下的功能
  • 定义一个Bean容器,HashMap结构,key是Bean名称,value是对应的类实例
//Bean容器
private static Map<String, Object> beanMap = new HashMap();
  • 工厂创建时即去获取所有的Bean对象,放到容器中管理,并对外提供获取Bean的方法
    • 解析beans.xml,获取所有的bean节点
    • 通过反射技术,根据bean节点class属性生成对象,放到Bean容器中
    • 获取bean节点的property子节点,进行属性注值(从bean容器中获取相应的Bean对象)
//工厂创建时即去构造Bean容器
static {
    loadBeans();
}
//加载Bean的方法
private static void loadBeans() {
        //1.读取bean配置文件
        InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");

        //通过dom4j工具进行解析
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            //获取到所有的bean节点
            List<Element> beanElements = rootElement.selectNodes("//bean");


            Map<String, Map<String, String>> propertyMap = new HashMap();

            for (Element beanElement : beanElements) {
                String id = beanElement.attributeValue("id");
                String clazz = beanElement.attributeValue("class");

                //通过反射技术创建类对象,放到Bean容器中
                Class<?> aClass = Class.forName(clazz);
                Object o = aClass.newInstance();
                beanMap.put(id, o);

                //获取bean节点的属性节点
                List<Element> propertyElements = beanElement.selectNodes("//property");

                //因为一个类可能有多个属性,所以这里也定义一个map属性来存储属性名称以及对应需要注入的对象的Bean名称
                Map<String, String> map = new HashMap<String, String>();
                for (Element propertyElement : propertyElements) {
                    String name = propertyElement.attributeValue("name");
                    String ref = propertyElement.attributeValue("ref");
                    map.put(name, ref);
                }

                //将获取到的属性数据,与bean对应起来,放到一个map中
                if(map.size() > 0){
                    propertyMap.put(id, map);
                }
            }

            //当所有Bean都实例化,放到了容器中后,再对Bean中的属性进行注入赋值
            Iterator<Map.Entry<String, Map<String, String>>> beanIterator = propertyMap.entrySet().iterator();

            while (beanIterator.hasNext()) {
                Map.Entry<String, Map<String, String>> beanEntry = beanIterator.next();
                //从容器中拿对应的Bean对象
                Object o1 = beanMap.get(beanEntry.getKey());
                //获取Bean的所有方法
                Method[] methods = o1.getClass().getMethods();

                //获取属性的迭代器
                Iterator<Map.Entry<String, String>> propertyIterator = beanEntry.getValue().entrySet().iterator();

                while (propertyIterator.hasNext()) {
                    Map.Entry<String, String> propertyEntry = propertyIterator.next();
                    //从容器中拿到属性引用的Bean对象
                    Object o2 = beanMap.get(propertyEntry.getValue());

                    //通过属性的setter方法进行赋值
                    for (Method method : methods) {
                        if (method.getName().equalsIgnoreCase("set" + propertyIterator.getValue())) {
                            method.invoke(o1, o2);
                        }
                    }
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 对外提供获取Bean对象的方法,从Bean容器中拿到相应对象
public static Object getBean(String beanName) {
        return beanMap.get(beanName);
    }
  1. 测试
  • 在配置文件中bean
<!--帐户DAO-->
<bean id="accountDao" class="com.yyh.dao.impl.AccountDaoImpl"/>

<!--转账业务Service-->
<bean id="transferService" class="com.yyh.service.impl.TransferServiceImpl">
    <property name="accountDao" ref="accountDao"/>
</bean>
  • TransferService的转账业务实现类中,实现转账功能
public class TransferServiceImpl implements TransferService {
    private AccountDao accountDao;


    public void transfer(String fromCardNumber, String toCardNumber, int money) throws SQLException {

        AccountEntity fromAccount = accountDao.selectOneByCardNumber(fromCardNumber);
        AccountEntity toAccount = accountDao.selectOneByCardNumber(toCardNumber);

        accountDao.updateMoneyByCardNumber(fromCardNumber, fromAccount.getMoney() - money);

        int a = 1 / 0;

        accountDao.updateMoneyByCardNumber(toCardNumber, toAccount.getMoney() + money);

    }
    
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
}
  • 在转账测试类TransferTest,调用转账的业务方法
public class TransferTest {
    private TransferService transferService = (TransferService) BeanFactory.getBean("transferService");

    @Test
    public void testTransfer() throws SQLException {
        transferService.transfer("123456", "123457", 100);
    }
}

项目代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值