一个小程序以理解控制反转
发布日期:2021-05-07 06:54:35 浏览次数:20 分类:技术文章

本文共 3309 字,大约阅读时间需要 11 分钟。

IOC即“控制反转”,即是将创建对象的操作,赋予给程序,而不需要程序员手动去修改代码,以达到解耦的效果,这部分的博文网上有很多,就不过多解释了

1. 实现思路

使用配置文件的方式,让程序运行时动态读取配置文件,从而得知要创建的对象的名字,然后通过反射机制动态创建该对象,从而实现控制反转

2. 控制反转的简单实现

① 创建以下层级目录及配置文件

在这里插入图片描述
② 编写factory.properties配置文件内容

helloDao=com.ruoxi.dao.impl.HelloDaoImpl

② 编写dao层

HelloDaoImpl.class

public class HelloDaoImpl implements HelloDao {       public HelloDaoImpl(){   };    @Override    public List
findAll() { return Arrays.asList("1","2","3","4","5"); }}

③ 创建一个Bean工厂,以提供生产HelloDaoImpl的实例

重点:

这里使用HashMap来模拟缓存,通过判断key是否存在来实现单例

如何实现控制反转?

(1) 通过properties.getProperty()函数,获取配置文件中的内容,以一个字符串接收,从而得到全类名

(2) 得到全类名,那么就可以调用Class.forName()得到对应的Class对象

(3) 得到Class对象,那么就可以创建一个对应类的实例(这里即是HelloDaoImpl)

具体见代码注释

public class BeanFactory {       private static Properties properties = new Properties();    // 使用HashMap模拟缓存    private static Map
cache = new HashMap<>(); //用静态代码块初始化属性值 static { try { properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("factory.properties")); //即factory.propertise配置文件 } catch (IOException e) { e.printStackTrace(); } } //传入参数beanName即为需要创建的实例名字 public static Object getDao(String beanName) { // 模拟IOC的单例模式 只能创建一个同名的bean 从缓存存取 // 如果缓存不存在名为beanName的bean,才进行初始化 if(!cache.containsKey(beanName)){ // 利用synchronized,确保多线程下的单例模式 synchronized (BeanFactory.class){ try { //读取配置文件中的值,用value来接收 String value = properties.getProperty(beanName); // value获取的即是配置文件中名为"helloDao"的接收值 //利用反射机制创建对象 这里创建的是名为value值的对象 Class clazz = Class.forName(value); Object object = clazz.getDeclaredConstructor(null).newInstance(null); //将bean名和object存入缓存 cache.put(beanName,object); return object; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } } return null; }}

④ 编写service层,调用dao层的函数

public class HelloServiceImpl implements HelloService {       private HelloDao helloDao = (HelloDao) BeanFactory.getDao("helloDao");    @Override    public List
findAll() { return helloDao.findAll(); }}

⑤ 编写HelloSerlvet.class进行测试

@WebServlet("/hello")public class HelloServlet extends HttpServlet {       private HelloService helloService =  new HelloServiceImpl();    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {           resp.getWriter().write(this.helloService.findAll().toString());    }}

在这里插入图片描述

测试成功

至此,简单的控制反转功能已经实现,为何这么说?

因为,当需要改变BeanFactory(bean工厂)生产的对象实例时,不需要再去改动java代码,只需要改动factory.properties中的内容

(这里即是右侧的HelloDaoImpl,如果需要生产其他实例则修改至对应的全类名即可)

helloDao=com.ruoxi.dao.impl.HelloDaoImpl

即是将生成对象实例的操作交给了程序,不需要改动代码,也就是达到了控制反转的功能

上一篇:手写框架,模拟简易的SpringIOC
下一篇:2019 CSP-S 被虐记

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2025年03月20日 20时44分07秒