Spring IOC 核心思想

IOC 核心思想

原视频链接

下面我们用JavaWeb的方式进行引入IOC的核心思想

1.导包

<!--servlet-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

<!--设置 maven jdk版本 默认为5 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

2.编写Servlet

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Spring");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3.在pom中修改war打包方式,添加tomcat并运行

<packaging>war</packaging>

在这里插入图片描述

4.Servlet、Service、Dao

HelloDao

public interface HelloDao {
    List<String> getAll();
}

HelloDaoImpl

public class HelloDaoImpl implements HelloDao {
    @Override
    public List<String> getAll() {
        return Arrays.asList("1","2","3");
    }
}

HelloService

public interface HelloService {
    List<String> getAll();
}

HelloServiceImpl

public class HelloServiceImpl implements HelloService {

    private static HelloDao  helloDao = new HelloDaoImpl();

    @Override
    public List<String> getAll() {
        return helloDao.getAll();
    }
}

HelloServlet

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    private static HelloService helloService = new HelloServiceImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write(helloService.getAll().toString());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在这里插入图片描述

当需求发生变更时,可能需要频繁修改Java代码,效率很低,如何解决?

使用静态工厂来创建特定的实现类,不再把代码写死到Service中

静态工厂

public class BeanFactory {
    public static HelloDao getDao(){
        return  new HelloDaoImpl();
    }
}
private HelloDao helloDao = BeanFactory.getDao();

上述方式并不能解决我们的问题,需求发生改变时,我们虽然无需修改Service,但还要修改BeanFactory中的代码。如何不改Java代码,就可以实现实现类的切换呢?

外部配置文件的方式

将具体的实现类写到配置文件中,Java程序只需要读取配置文件即可。

1.定义外部配置文件

factory.properties

helloDao = com.demo.dao.impl.HelloDaoImpl

2.Java程序读取这个配置文件

public class BeanFactory {

    private static Properties properties;

    // 实例化properties
    static {
        properties = new Properties();
        try {
			//读取配置文件            
            properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("factory.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Object getDao(){
        String value = properties.getProperty("helloDao");
        System.out.println(value);//com.demo.dao.impl.HelloDaoImpl
        // 反射机制创建对象
        try {
            Class clazz = Class.forName(value);
            Object obj = null;
            try {
                obj = clazz.getConstructor().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            return  obj;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return  null;
    }
}

3.修改Service

private HelloDao helloDao = (HelloDao) BeanFactory.getDao();

4.测试
在这里插入图片描述

Spring IOC 中的bean是单例

此时我们利用工厂创建出来的对象不是单例,我们还需优化 — 缓存

BeanFactory

利用Map集合创建缓存已经生成的对象,并使用双重检测锁来维护单例模式。

private static Map<String, Object> cache = new HashMap<>();


public static Object getDao(String beanName) {
        // 判断缓存中是否存在Bean
        if (!cache.containsKey(beanName)) {
            synchronized (BeanFactory.class) {
                if (!cache.containsKey(beanName)) {
                    // 将bean存入缓存
                    // 反射机制创建对象
                    try {
                        String value = properties.getProperty(beanName);//com.demo.dao.impl.HelloDaoImpl
                        Class clazz = Class.forName(value);
                        Object obj = clazz.getConstructor().newInstance();
                        // 存入缓存
                        cache.put(beanName,obj);
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
        return cache.get(beanName);
    }

在这里插入图片描述
总结

1private HelloDao helloDao = new HelloDaoImpl();

2private HelloDao helloDao = (HelloDao) BeanFactory.getDao("helloDao");

1、强依赖/紧耦合,编译之后无法修改,没有扩展性;

2、弱依赖/松耦合,编译之后仍然可以修改,让程序具有更好的扩展性。

自己放弃了创建对象的权限,将创建对象的权限交给了BeanFactory,这种将控制权交给别人的思想,就是控制反转IOC。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值