Spring初探之手写实现简单的beanFactory

本文通过手动创建beanFactory,详细讲解如何实现Spring中bean的实例化过程,包括注册bean、实例化对象,并深入探讨了bean的scope属性,解释了singleton和prototype两种模式的区别。通过示例代码,展示了不同scope属性下bean的实例化结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手写简单的beanFactory主要分两步:
1、定义bean对象,对应Spring中的< bean >标签;
2、创建BeanFactory,根据 BeanFactory 来获取实例对象;
bean定义对象:

package com.lks.util;

/**
 * Created by likaisong on 2019/3/3.
 */
public class BeanDefined {

    private String beanId;

    private String classPath;

    public void setClassPath(String classPath) {
        this.classPath = classPath;
    }

    public String getBeanId() {

        return beanId;
    }

    public String getClassPath() {
        return classPath;
    }
}

创建beanFactory

package com.lks.util;

import java.util.List;

/**
 * Created by likaisong on 2019/3/3.
 */
public class BeanFactory {
    private List<BeanDefined> beanDefinedList;

    public List<BeanDefined> getBeanDefinedList() {
        return beanDefinedList;
    }

    public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
        this.beanDefinedList = beanDefinedList;
    }

    /**
     *  通过反射实例化对象
     * @param beanId
     * @return
     * @throws Exception
     */
    public Object getBean(String beanId) throws Exception {
        Object instance = null;
        for (BeanDefined bean : beanDefinedList){
            if (beanId.equals(bean.getBeanId())){
                String classPath = bean.getClassPath();
                instance = Class.forName(classPath).newInstance();
                return instance;
            }
        }
        return instance;
    }
}

其中最主要的是getBean() 方法,利用反射机制,获取到对象,然后调用 newInstance() 默认的构造方法进行实例化,最后返回一个实例化好的对象,Spring 就是利用类似这样反射工厂的方式进行对象的实例化的。
测试类TestMain.java:

package com.lks.util;

import com.lks.bean.User;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by likaisong on 2019/3/3.
 */
public class TestMain {
    @Test
    public void testBeanFactory() throws Exception {
        //注册bean
        BeanDefined beanDefined = new BeanDefined();
        beanDefined.setBeanId("user");
        beanDefined.setClassPath("com.lks.bean.User");
        List<BeanDefined> beanDefineds = new ArrayList<BeanDefined>(16);
        beanDefineds.add(beanDefined);

        //声明BeanFactory,类似于Spring中的ApplicationContext
        BeanFactory factory = new BeanFactory();
        factory.setBeanDefinedList(beanDefineds);

        //实际调用
        User user = (User) factory.getBean("user");
        System.out.println(user);
    }
}

这里主要分三步:
1、注册bean,相当于在 Spring 配置文件中添加 < bean > 标签;
2、将注册好的 bean 添加到 BeanFactory 中,使 bean 能够被 BeanFactory 管理,就如 Spring 中 bean 添加到 Spring 容器中一样;
3、通过 BeanFactory 来进行对象的实例化
通过简单的三步,一个类的实例化就完成了,这只是一个最简单的BeanFactory。
为了加深对BeanFactory以及< bean > 标签中的 scope 属性的理解,我们下面在前面一个beanFactory的基础上,实现自己的 scope 属性的功能。
scope 属性有两个值,分别是 prototype(原型)和 singleton(单例)
singleton: 在 Spring 容器启动时,被标记的类创建并保存在 Spring 框架 SingletonList 中,每次都只会返回同一个实例对象。
prototype: Spring 容器在启动时,被标记的类不会被创建,每次都会返回一个全新的实例对象。
在bean定义对象中新增bean scope属性:

package com.lks.util;

/**
 * Created by likaisong on 2019/3/3.
 */
public class BeanDefined {

    private String beanId;

    private String classPath;

    //和Spring一样,默认是单例
    private String beanScope = "singleton";

    public void setBeanScope(String beanScope) {
        this.beanScope = beanScope;
    }

    public String getBeanScope() {

        return beanScope;
    }

    public void setClassPath(String classPath) {
        this.classPath = classPath;
    }

    public String getBeanId() {

        return beanId;
    }

    public String getClassPath() {
        return classPath;
    }

    public void setBeanId(String beanId) {
        this.beanId = beanId;
    }
}

BeanFactory中处理scope属性,根据scope属性的值返回实例化对象:

package com.lks.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by likaisong on 2019/3/3.
 */
public class BeanFactory {
    //存放bean集合
    private List<BeanDefined> beanDefinedList;

    private Map<String, Object> springIoc;

    public BeanFactory(){

    }

    public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
        this.beanDefinedList = beanDefinedList;
        springIoc = new HashMap<String, Object>(16);
        for (BeanDefined bean: beanDefinedList){
            if ("singleton".equals(bean.getBeanScope())){
                String classPath = bean.getClassPath();
                Object instance = Class.forName(classPath).newInstance();
                springIoc.put(bean.getBeanId(), instance);
            }
        }
    }

    public List<BeanDefined> getBeanDefinedList() {
        return beanDefinedList;
    }

    public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
        this.beanDefinedList = beanDefinedList;
    }

    /**
     *  通过反射实例化对象
     * @param beanId
     * @return
     * @throws Exception
     */
    public Object getBean(String beanId) throws Exception {
        Object instance = null;
        for (BeanDefined bean : beanDefinedList){
            if (beanId.equals(bean.getBeanId())){
                String classPath = bean.getClassPath();
                instance = Class.forName(classPath).newInstance();
                return instance;
            }
        }
        return instance;
    }

    /**
     * 根据scope属性获取实例化对象
     * @param beanId
     * @return
     * @throws Exception
     */
    public Object getScopeBean(String beanId) throws Exception {
        Object instance = null;
        for (BeanDefined bean: beanDefinedList){
            if (beanId.equals(bean.getBeanId())){
                String classPath = bean.getClassPath();
                if ("singleton".equals(bean.getBeanScope())){
                    instance = springIoc.get(beanId);
                } else {
                    instance = Class.forName(classPath).newInstance();
                }
            }
        }
        return instance;
    }
}

这里定义一个Map根据beanId存放需要实例化的对象,如果scope的属性值是singleton的话,就把实例化对象存放在map中,在getScopeBean方法中根据scope的值返回已经实例化的对象或者是新实例化的对象。
测试类中的写法基本和上面的testBeanFactory方法差不多,只不过是新增了scope的赋值方法
如果scope的属性值是 prototype的话:
在这里插入图片描述
打印出来的是两个完全不同的实例对象。
如果scope的属性值是 singleton的话:
在这里插入图片描述
打印出来的是同一个实例对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值