spring简介

87 阅读3分钟

参考 编程界翁老师 之课程及资料:gitee.com/hadoop101/d…
(代码对应的视频在 space.bilibili.com/524750627/v…

1)手写迷你"框架",模拟 Spring解决"new实例带来的三个问题"

不通过框架,手动new对象有3个缺点:

1.创建出来的对象,其类型不方便修改(不能控制类型)
2.频繁地new对象,会导致对象的数量过多(不能控制数量)
3.有些类对象,我们希望在项目启动的时候 实例化,而不是在 要使用的时候 才实例化(不能控制时机)

为了解决以上3个缺点,可以模仿spring原理,写一个demo(仅列出关键代码):

测试方法:

public class TestFactory {
    /*
        测试方法 test01()
        模拟 账户的创建
     */
    @Test
    public void test01() {
        //1:定义一个业务类:账户Service
        AccountService as = new AccountServiceImpl();

        //2:创建一个账户数据
        Account account = new Account(1001L, "jack", 1000.000);

        //3:账户数据 添加,更新,查找
        as.saveAccount(account);
        as.updateAccount(account);

        Account acc = as.findAccount(1001L);
        System.out.println(acc);
    }

    /*
        测试方法 test01()
        模拟 单例模式 创建 AccountService 对象
     */
    @Test
    public void test2() {
        System.out.println("test2");

        //1:定义 两个业务类(账户Service)的 对象
        AccountService as1 = (AccountService) MyBeanFactory.getBean("service", "singleton");
        AccountService as2 = (AccountService) MyBeanFactory.getBean("service", "singleton");
        System.out.println(as1);
        System.out.println(as2);

        //2:创建一个账户数据
        Account account = new Account(1001L, "jack", 1000.000);

        //3:账户数据 添加,更新,查找
        as1.saveAccount(account);
        as1.updateAccount(account);

        Account acc = as1.findAccount(1001L);
        System.out.println(acc);
    }

}

通过 工厂模式+读取配置文件+反射,模拟Spring创建类对象(可认为 MyBeanFactory类 是一个“迷你Spring框架”):


// 1:工厂类
public class MyBeanFactory {
    // 2:容器(container)创建(模仿创建了一个Spring容器)
    private static Map<String, Object> container = new HashMap<String, Object>();
    private static Properties properties;

    // 3:
    // 静态代码块中 通过读取配置文件
    // 加载 类信息 到 properties对象中
    static {
        // 加载类型信息
        properties = new Properties();
        // 解析
        InputStream is = MyBeanFactory.class.getResourceAsStream("/mybean.properties");
        try {
            properties.load(is);
            //可以这里初始化对象,放到容器中,也可以在使用时再初始化
        } catch (IOException e) {
        }
    }

    //4:查找对象(类似单例模式、工厂模式)
    public static Object getBean(String id, String singleton) {
        if ("singleton".equals(singleton)) {
            //查找 container中是否已有 所需类(如AccountServiceImpl类)的对象
            Object obj = container.get(id);
            //容器里面没有 所需 类的对象
            if (obj == null) {
                String str = properties.getProperty(id);
                Class clz = null;
                try {
                    clz = Class.forName(str);
                    Object o = clz.newInstance();
                    // 把 新对象 添加到容器中
                    container.put(id, o);
                    return o;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                //重用(复用)同一个对象
                return obj;
            }
        } else {
            // 多实例 prototype
            // 容器(container)里面没有 所需 类(如AccountServiceImpl类)的对象
            String str = properties.getProperty(id);
            Class clz = null;

            try {
                clz = Class.forName(str);
                Object o = clz.newInstance();
                return o;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

配置文件(mybean.properties)的内容:

service=service.impl.AccountServiceImpl
dao=dao.impl.AccountDaoImpl

mybean.properties test1()方法的运行结果,可见AccountService手动new出来,随后执行CURD方法: test1()方法的运行结果 test2()方法的运行结果,可见AccountService对象 被MyBeanFactory类(的静态方法getBean)所创建,且为单例模式,随后执行CURD方法: test2()方法的运行结果

2) 同上套路,写一个Spring入门程序

pom文件中,导入spring:

        <!-- spring基础-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

配置文件(beans.xml)的内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="dao.impl.AccountDaoImpl" id="dao"></bean>
    <bean class="service.impl.AccountServiceImpl" id="service" scope="prototype"></bean>

</beans>

测试方法:

public class TestFactory {
    @Test
    public void test01() {
        // 1:使用maven依赖了spring基本包

        // 2:初始化spring ioc容器
        // BeanFactory满足基本功能的容器:顶层接口
        // ApplicationContext高级功能的容器:子抽象类
        // ClassPathXmlApplicationContext实现类
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");
        // 3:获取service对应的对象
        AccountService as1 = (AccountService) beanFactory.getBean("service");
        AccountService as2 = (AccountService) beanFactory.getBean("service");

        System.out.println(as1);
        System.out.println(as2);

        as1.saveAccount(null);
    }
}

留意ClassPathXmlApplicationContext类(以上代码通过此类的对象,加载配置文件、创建类对象),它继承了抽象类AbstractApplicationContext,实现了BeanFactory接口: ClassPathXmlApplicationContext类 test01()方法的运行结果如下, 可见AccountService对象被ClassPathXmlApplicationContext对象beanFactory 所创建,且为单例模式(由于在beans.xml中配置了 scope="prototype"):