参考 编程界翁老师 之课程及资料: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
test1()方法的运行结果,可见AccountService手动new出来,随后执行CURD方法:
test2()方法的运行结果,可见AccountService对象 被MyBeanFactory类(的静态方法getBean)所创建,且为单例模式,随后执行CURD方法:
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接口:
test01()方法的运行结果如下, 可见AccountService对象被ClassPathXmlApplicationContext对象beanFactory 所创建,且为单例模式(由于在beans.xml中配置了 scope="prototype"):