模仿spring的核心容器创建单例对象
程序员文章站
2024-03-24 16:32:28
...
模仿spring的核心容器创建单例对象
项目结构
配置文件
-
bean.properties
accountService = com.xiaoge.service.impl.AccountServiceImpl accountDao = com.xiaoge.dao.impl.AccountDaoImpl
持久层接口
-
AccountDao
package com.xiaoge.dao; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:31 * @Description: TODO */ public interface AccountDao { public void saveAccount(); }
持久层实现类
-
AccountDaoImpl
package com.xiaoge.dao.impl; import com.xiaoge.dao.AccountDao; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:31 * @Description: TODO */ public class AccountDaoImpl implements AccountDao { public void saveAccount() { System.out.println("保存成功!"); } }
业务层接口
-
AccountService
package com.xiaoge.service; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:26 * @Description: 账户业务层接口 */ public interface AccountService { /** * 模拟保存 */ public void saveAccount(); }
业务层实现类
-
AccountServiceImpl
package com.xiaoge.service.impl; import com.xiaoge.dao.AccountDao; import com.xiaoge.factory.BeanFactory; import com.xiaoge.service.AccountService; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:28 * @Description: 账户业务层实现类 */ public class AccountServiceImpl implements AccountService { private AccountDao accountDao = (AccountDao)BeanFactory.getBean("accountDao"); public void saveAccount() { accountDao.saveAccount(); } }
工厂
-
BeanFactory
package com.xiaoge.factory; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:54 * @Description: TODO * * Bean, 在计算机英语中, 有可重用组件的含义. * JavaBean: 用java语言编写的可重用组件. * javabean > 实体类 * * 它就是创建我们的service和dao对象的. * * 第一个: 需要一个配置文件来配置我们的service和dao * 配置的内容: 唯一标识 = 全限定类名 (key = value) * * 第二个: 通过读取配置文件中配置的内容, 反射创建对象. * * 配置文件可以是xml也可以是properties */ public class BeanFactory { private static Properties prop = null; // 定义一个map, 用于存放我们要创建的对象, 我们把它称职为容器 private static Map<String, Object> beans; // 注意: 静态变量, 跟实例没关系, 静态变量只能出现在静态方法中, 值是会根据静态方法修改它而修改的 // 而成员变量, 是根据实例走的, 每创建一个实例, 成员变量就会被初始化一遍 // 在类加载的init阶段,类的类构造器中会收集所有的static块和字段并执行,static块只执行一次,由JVM保证其只执行一次。 // 加载顺序: 一般顺序:静态块(静态变量)——>成员变量——>构造方法——>静态方法 static { try { InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); // 实例化对象 prop = new Properties(); prop.load(is); // 实例化容器 beans = new HashMap<String, Object>(); // 获取配置文件中的所有key Enumeration keys = prop.keys(); // 遍历keys while(keys.hasMoreElements()) { // 获取每一个key String key = (String)keys.nextElement(); // 获取每个key对应的权限定类名 String ClassPath = prop.getProperty(key); // 将全限定类名加载进内存, 并创建对象 Object value = Class.forName(ClassPath).newInstance(); // 将数据添加进map beans.put(key, value); } } catch (IOException e) { throw new ExceptionInInitializerError("初始化properties失败!"); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 根据Bean名称创建Bean对象 (单例) * @param beanName * @return */ public static Object getBean(String beanName) { Object bean = null; // 获取map中对应键的值, 并且返回, 当map集合中没有该键, 直接抛出异常 bean = beans.get(beanName); System.out.println(bean); return bean; } /** * 根据Bean名称获取Bean对象 (多例) * @param beanName * @return public static Object getBean(String beanName) { Object bean = null; String name = prop.getProperty(beanName); // 把权限定类名加载进内存, 并且创建一个实例化对象 try { bean = Class.forName(name).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return bean; } */ }
main
-
Client
package com.xiaoge.ui; import com.xiaoge.factory.BeanFactory; import com.xiaoge.service.AccountService; /** * @Author: 潇哥 * @DateTime: 2020/3/19 下午7:35 * @Description: 模拟表现层, 调用业务层 */ public class Client { public static void main(String[] args) { // AccountService accountService = new AccountServiceImpl(); for (int i = 0; i < 5; i++) { AccountService accountService = (AccountService)BeanFactory.getBean("accountService"); accountService.saveAccount(); } // 运行结果 com.xiaoge.dao.impl.AccountDaoImpl@610455d6 com.xiaoge.service.impl.AccountServiceImpl@511d50c0 保存成功! com.xiaoge.service.impl.AccountServiceImpl@511d50c0 保存成功! com.xiaoge.service.impl.AccountServiceImpl@511d50c0 保存成功! com.xiaoge.service.impl.AccountServiceImpl@511d50c0 保存成功! com.xiaoge.service.impl.AccountServiceImpl@511d50c0 保存成功! } }
上一篇: 异常注意事项
下一篇: mybatis的分页插件