依赖注入的方法总结

122 阅读5分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

1 IOC介绍

Spring是一个开源的、松耦合的、分层的、可配置的、一站式的企业级Java开发框架,核心是IOC和AOP。

其中本文要介绍的就是IOC的一种实现方法依赖查找(DL)。

现在先介绍一下IOC:

IOC(控制反转)不是一种技术,而是一种思想。在以往的编程过程中,都是我们主动的在类的内部创建需要的对象,这种对象就是我们所看到的依赖对象。这种方法导致的一个问题就是,类和类之间的耦合度超高,不便于业务的扩展和修改,以及及其难以测试。

而IOC的思想就是,将原来我们手动new bean的权力交出去,交给Spring去做,而放置和管理这些bean的就是IOC容器。就像在没有餐馆以前,你想要吃什么菜,你要自己根据食谱(类Class),来自己制作一道菜(对象Bean)。而现在你想吃什么就去点菜,厨子(Spring)会把菜给你做好,并送到你的餐桌上。

2 准备工作

首先要创建一个Maven项目,这里就不过多赘述,网上有很好的教学文章或视频。

2.1 引入依赖

这里我们主要体验一下几种使用xml文件来体验一把依赖查找,就只要在pom.xml文件中引入一个依赖spring-context

1-2.1 依赖文件.png

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

2.2 创建配置文件

可以理解成请一个厨子,里面装的都是他会做的菜品。

创建一个xml文件

1-2.2 创建依赖文件.png

初始化配置(新来的厨子啥也不会):

<?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">

</beans>

2.3 创建一些类

搞几个菜谱,这里我们创建了麻婆豆腐和北京烤鸭(中国菜的名字真的好长)

1-2.3 创建类.png

//北京烤鸭
public class BeijingRoastDuck {

}
//麻婆豆腐
public class MapoTofu {

}

2.4 创建启动类

这里我们创建一个点菜通过名字的启动类,然后这里使用main函数

public class OrderByNameApplication {
    public static void main(String[] args) {

    }
}

2.5 在配置文件进行声明

就是给厨子菜谱,在配置文件给这些菜声明一下

<?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 id="BeijingRoastDuck" class="com.shea.restaurant.bean.BeijingRoastDuck"></bean>
    <bean id="MapoTofu" class="com.shea.restaurant.bean.MapoTofu"></bean>
</beans>

餐馆一切都准备好了,接下来就是点菜了。

3 依赖查找的方式

可以理解成为,你去餐厅点菜,使用的是什么方式。

3.1 通过名字查找

通过菜名点菜。主要的方法getBean(String s)

你去到餐厅,开始点菜:

你:“欸,我想吃这个北京烤鸭,你这有不?”

厨子:“我看看啊!欸!有!”

那这个过程就是:

public class OrderByNameApplication {
    public static void main(String[] args) {
        //创建IOC容器 点菜的时候把厨子叫过来
        BeanFactory factory = new ClassPathXmlApplicationContext("cook.xml");
        //查找依赖 你和厨子点菜 厨子想一下会不会
        BeijingRoastDuck beijingRoastDuck = (BeijingRoastDuck) factory.getBean("BeijingRoastDuck");

        //这里我们就看看厨子的菜谱没有没找对(验证一下)
        System.out.println(beijingRoastDuck);
    }
}

打印的内容:

1-3.1 通过名字查找.png

这个过程就是通过我们配置文件的id进行依赖查找,查找到依赖对象所在的类

3.2 通过类查找

通过食谱点菜,主要的方法getBean(Object object)

这次你去餐馆点菜,你有一个菜谱,但是不知道菜名,你就给厨子看:

你:“哥,我这有个菜谱,你看你会这个菜不?”

厨子:“我瞅瞅啊,欸!这个我会呀!给你做哈!”

过程如下:

public class OrderByTypeApplication {
    public static void main(String[] args) {
        //创建IOC容器 点菜的时候把厨子叫过来
        BeanFactory factory = new ClassPathXmlApplicationContext("cook.xml");
        //查找依赖 你不知道菜名,但是知道菜谱,你给厨子看,厨子看看自己会不会
        MapoTofu mapoTofu = factory.getBean(MapoTofu.class);
        //这里看看厨子会不会这个菜谱
        System.out.println(mapoTofu);
    }
}

打印内容:

1-3.2 通过食谱查找.png

这个方法就不需要进行强制类型转换了,都把类传进去了

3.3 取出所有类

通过菜单点菜,主要方法getBeansOfType(Object object)

这天你又去吃饭,但是你每啥头绪,然后你就想看看这厨子都会哪些菜

你:“今天不知道吃啥,可以看看你的菜谱吗?”

厨子:”没问题!“

过程如下:

这个时候我们就不能用BeanFactory我们要改用ApplicationContext,当然上面的BeanFactory是可以换成ApplicationContext的,两者的关系就是ApplicationContextBeanFactory的子接口,同时官方也建议都使用ApplicationContext,因为它的功能更加丰富,性能更加优秀。

在进行这一步的操作前,我们先定义一个接口Food

public interface Food {
    
}

然后将我们的菜类全部实现这个接口,目录结构如下:

1-3.3 接口.png

记得修改配置文件中的bean目录

<?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 id="BeijingRoastDuck" class="com.shea.restaurant.bean.impl.BeijingRoastDuck"></bean>
    <bean id="MapoTofu" class="com.shea.restaurant.bean.impl.MapoTofu"></bean>
</beans>

启动类:

public class OrderOfTypeApplication {
    public static void main(String[] args) {
        //创建IOC容器 点菜的时候把厨子叫过来
        ApplicationContext factory = new ClassPathXmlApplicationContext("cook.xml");
        //查找依赖 你想看看厨子都会做什么菜
        Map<String, Food> beans = factory.getBeansOfType(Food.class);
        //厨子会做的菜和菜谱
        beans.forEach((beanName, bean) -> {
            System.out.println(beanName + " : " + bean.toString());
        });
    }
}

打印内容:

1-3.3-1 打印内容.png

3.4 通过注解查找

通过菜的类别点菜,主要方法getBeansWithAnnotation(Object object)

你今天特别想吃北京菜,于是你去餐馆问厨子:

你:”你会做啥北京菜啊?“

厨子:“我给你看看”

我们先创建一个注释,叫BeijingFood

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BeijingFood {
    
}

然后在北京烤鸭上面写这个注释

@BeijingFood
public class BeijingRoastDuck implements Food {

}

启动类:

public class OrderByAnnotationApplication {
    public static void main(String[] args) {
        //创建IOC容器 点菜的时候把厨子叫过来
        ApplicationContext factory = new ClassPathXmlApplicationContext("cook.xml");
        //查找依赖 你想看看厨子都会做什么北京菜
        Map<String, Object> beans = factory.getBeansWithAnnotation(BeijingFood.class);
        //厨子会做的菜和菜谱
        beans.forEach((beanName, bean) -> {
            System.out.println(beanName + " : " + bean.toString());
        });
    }
}

打印内容:

1-3.4 打印内容.png