(四) IoC——依赖注入(DI)

1. 基于XML的DI
1.1 注入分类

   bean实例在调用无参构造器创建了空值对象后,就要对bean对象的属性进行初始化,属性初始化是由容器自动完成的,称为注入。根据注入方式的不同,常用的有两类:设值注入、构造注入。

  • 设值注入
       设值注入是指,通过Java类中的setter方法给属性赋值,优点是简单、直观,因而在Spring的依赖注入中大量使用。
  • 构造注入
       构造注入是指,通过调用Java类中的有参构造方法,在创建对象的同时,给属性赋值。

   现在有School类——只包含简单类型属性,Student类——包含简单类型属性和引用类型属性,来看看如何在XML中进行DI。

School.java

public class School {

    public String address;

    private String name;

    public School(){}

    public School(String address, String name){
        this.address = address;
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Student.java

public class Student {

    private int age;

    public School school;

    public Student(){}

    public Student(int age, School school) {
        this.age = age;
        this.school = school;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;

    }
}
1.1.1 设值注入

   在XML配置文件中,使用<property />标签,完成属性的赋值。

  • 简单类型(String和Java基本数据类型)的设值注入:
    <bean id="school" class="com.lyj.main.beans.School">
        <property name="address" value="China"/>
        <property name="name" value="Hnu"/>
    </bean>
  • 引用类型的设值注入:
    <bean id="student" class="com.lyj.main.beans.Student">
        <property name="age" value="20"/>
        <!-- 语法一:ref作为标签属性 -->
        <property name="school" ref="school"/>
        <!-- 语法二:ref作为子标签 -->
        <!--<property name="school">-->
            <!--<ref bean="school"/>-->
        <!--</property>-->
    </bean>

   其中,"name”是属性名称,“value”是赋的属性值,<ref />的“bean”是引用对象的<bean>的“id”。

1.1.2 构造注入

   在XML配置文件中,使用<constructor-arg />标签,完成属性的赋值,一个<constructor-arg />标签对应一个构造函数中的形参。

  • 使用“name”属性:
    <bean id="school_" class="com.lyj.main.beans.School">
        <constructor-arg name="address" value="China"/>
        <constructor-arg name="name" value="Hnu"/>
    </bean>
    
    <bean id="student_" class="com.lyj.main.beans.Student">
        <constructor-arg name="age" value="20" />
        <constructor-arg name="school" ref="school_"/>
    </bean>

   <constructor-arg />标签中,“name”是构造函数的形参名,“value”是简单类型的值,“ref”是引用类型的值。

  • 使用“index”属性:
    <bean id="student__" class="com.lyj.main.beans.Student">
        <constructor-arg index="0" value="20" />
        <constructor-arg index="1" ref="school_"/>
    </bean>
    
    <!-- 省略index属性 -->
    <bean id="student___" class="com.lyj.main.beans.Student">
        <constructor-arg value="20" />
        <constructor-arg ref="school_"/>
    </bean>

   <constructor-arg />标签中,"index"是构造方法中参数的位置,从0开始。

1.2 具有集合性质的属性注入

bean类——MyCollection.java

public class MyCollection {

    private String[] strs;
    private List<Student> students;
    private Set<String> set;
    private Map<String, Student> map;
    private Properties properties;
    private List<Map<String, String>> mapList;

    public void setStrs(String[] strs) {
        this.strs = strs;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, Student> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void setMapList(List<Map<String, String>> mapList) {
        this.mapList = mapList;
    }

}
  • 为数组(array)注入值:
        <!-- Array<String> -->
        <property name="strs">
            <array>
                <value>张三</value>
                <value>李四</value>
            </array>
        </property>
  • 为List注入值:
        <property name="students">
            <list>
                <ref bean="student"/>
                <ref bean="student_"/>
                <ref bean="student__"/>
            </list>
        </property>
  • 为Set注入值:
        <!-- Set<String> -->
        <property name="set">
            <set>
                <value>北京</value>
                <value>上海</value>
            </set>
        </property>
  • 为Map注入值:
        <!-- Map<String, Student> -->
        <property name="map">
            <map>
                <entry key="张三" value-ref="student"/>
                <entry key="李四" value-ref="student_"/>
            </map>
        </property>
  • 为Properties注入值:
        <!-- Properties key-value均为String -->
        <property name="properties">
            <props>
                <prop key="phone">123456</prop>
                <prop key="address">北京朝阳区</prop>
            </props>
        </property>
  • 复杂(嵌套)集合属性的注入:
        <!-- List<Map<String, String>> -->
        <property name="mapList">
            <list>
                <map>
                    <entry key="name" value="张三"/>
                    <entry key="weight" value="80kg"/>
                </map>
                <map>
                    <entry key="name" value="李四"/>
                    <entry key="weight" value="100kg"/>
                </map>
            </list>
        </property>
1.3 引用类型属性的自动注入

   由框架给引用类型完成赋值,使用<bean/>标签的"autowire"属性,赋值的方式主要有"byName"、“byType”。

  • byName:按名称注入,Java类中引用类型的属性名和spring容器(xml配置文件)中<bean>的"id"一致,且数据类型一致。
    <bean id="studentA" class="com.lyj.main.beans.Student" autowire="byName">
        <property name="age" value="20"/>
    </bean>
  • byType:按类型注入,Java类中引用类型的数据类型和spring容器(xml配置文件)中/的"class"属性值是同源关系——相同类、父类和子类关系、接口和实现类关系。(注意:符合条件的对象只能有一个,否则会报错)
    <bean id="studentB" class="com.lyj.main.beans.Student" autowire="byType">
        <property name="age" value="20"/>
    </bean>
1.4 为应用指定多个spring配置文件
  • 平等关系的配置文件(相互独立

applicationContext.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 id="school" class="com.lyj.main.beans.School">
        <property name="address" value="China"/>
        <property name="name" value="hnu"/>
    </bean>

    <bean id="student" class="com.lyj.main.beans.Student">
        <property name="age" value="20"/>
    </bean>

</beans>

   假设我们有配置文件applicationContext.xml,可以将其拆分为两个独立的配置文件——spring-student.xml、spring-school.xml:

spring-student.xml(引用其他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="student" class="com.lyj.main.beans.Student" autowire="byType">
        <property name="age" value="20"/>
    </bean>
</beans>

spring-school.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 id="school" class="com.lyj.main.beans.School">
        <property name="address" value="China"/>
        <property name="name" value="hnu"/>
    </bean>
</beans>

   创建容器对象时,将另个配置文件的路径一同传入即可:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-school.xml", "spring-student.xml");
  • 包含关系的配置文件
       各配置文件中有一个总文件,总配置文件将其他子文件通过<import/>引入,在Java代码中只需要使用总配置文件对容器进行初始化即可。(注意:总配置文件一般不定义bean对象)

total.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">

    <import resource="spring-school.xml"/>
    <import resource="spring-student.xml"/>

</beans>

   也可以使用通配符“*”,注意不能将总配置文件包含进去。

    <import resource="spring-*.xml"/>
2. 基于注解的DI

   spring容器对于Bean的创建和对象属性的依赖注入提供了注解的支持,Spring 中使用注解,需要在原有 Spring 运行环境基础上再做一些改变,完成以下三个步骤:

  • 导入 AOP 的 Jar 包。因为注解的后台实现用到了 AOP 编程。
    AOP的jar包
  • 需要更换配置文件头,即添加相应的约束。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    
</beans>
  • 需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
    <context:component-scan base-package="com.lyj.main2" />

   如果需要包含多个包,可以定义多个<component-scan>,也可以在“base-package”属性中使用 ‘,’ 或 ‘;’ 进行分隔,或者直接指定到父包名。

2.1 定义Bean的注解——@Component

   需要在类上使用注解@Component,表示创建该类的对象(默认为单例对象),该注解的“value”属性用于指定该 bean 的 id 值。

@Component(value="school")  // 显式指定id,等同于 <bean id="school" class="..."/>
//@Component("school")  //只有一个value属性时,可省略
//@Component()  //如果未定义id,则默认为首字母小写的类名名称——school
public class School {

    private String address;

    private String name;
}

   另外,Spring 还提供了 3 个功能基本和@Component 等效的注解:

  • @Repository 用于对 DAO 实现类进行注解;
  • @Service 用于对 Service 实现类进行注解;
  • @Controller 用于对 Controller 实现类进行注解;

   之所以创建这三个功能与@Component 等效的注解,是为了以后对其进行功能上的扩展。

2.2 简单类型属性注入——@Value

   需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上。

@Component("school")
public class School {
    @Value("北京")
    private String address;

    private String name;

    @Value("北京大学")
    public void setName(String name) {
        this.name = name;
    }
}
2.3 引用类型属性注入——@Autowired

   需要在属性上使用注解@Autowired,同样的,也可将其加到 setter 上。

  • byType方式(默认)
@Component()
public class Student {
    @Value("20")
    private int age;

    @Autowired
    private School school;
}
  • byName方式
@Component()
public class Student {

    @Value("20")
    private int age;

    @Autowired
    @Qualifier(value = "mySchool")  // 定义id名称
    private School school;
}

   @Autowired 还有一个属性 required,默认值为 true,表示当匹配失败后,程序会终止运行。若将其值设置为 false,则匹配失败后程序不会终止运行,未匹配的属性值为 null。

    @Autowired(required = false)
    private School school;
2.4 引用类型属性注入——@Resource

   Spring提供了对 jdk中@Resource注解的支持,@Resource 注解既可以按名称匹配Bean,也可以按类型匹配 Bean,默认是按名称注入。注意,使用该注解,要求 JDK 必须是 6 及以上版本。类似地,@Resource 可在属性上,也可在 set 方法上。

  • 按类型匹配Bean
       @Resource 注解若不带任何参数,采用默认按属性名称的方式注入,按名称不能注入 bean,则会按照类型进行 Bean 的匹配注入。
@Component()
public class Student {

    @Value("20")
    private int age;

    @Resource
    private School school;
}
  • 按名称匹配Bean
       @Resource 注解指定其“name”属性,则“name”的值即为按照名称进行匹配的 Bean 的 id。
2.5 Bean的生命始末——@PostConstruct 、@PreDestroy

   在初始化方法上使用@PostConstruct ,与XML配置方式的<bean init-method=""> 等效;在销毁方法上使用@PreDestroy,与XML配置方式的<bean destroy-method=""> 等效。

    @PostConstruct
    public void init(){
        System.out.println("执行初始化操作...");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("执行销毁前的处理操作...");
    }
3. 基于XML与基于注解的对比
  • XML配置方式
       优点:对其所做修改,无需编译代码,只需重启服务器即可将新的配置加载;在没有源代码的情况下,使用不了@Compoent 等注解,此时使用 XML 进行配置 bean。
       缺点:代码多,使用麻烦,开发效率低。

  • 注解配置方式
       优点:配置方便、简单,开发效率高,可读性高,在阅读源码时就可以知道属性的信息。
       缺点:以硬编码的方式写入到了Java代码中,其修改是需要重新编译代码的。

  • 总结
       所以,在实际工程中,一般是两者结合使用,大部分Bean类使用注解配置方式,而对需要经常修改的Bean类使用XML配置方式。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值