Spring中IOC容器和DI属性注入学习详解

IOC底层实现与结论

IOC,指的是控制反转,以往我们要使用一个类,需要手动去new,使用spring框架后,这一步就可以交给spring框架处理,相当于把对象的控制权交给了spring框架,所以叫控制反转;

IOC的底层实现其实很简单,创建一个BeanFactory,用xml解析器获取xml中配置好的类,再利用反射新建一个类,以下是代码实现;

  • 导包
 		<!-- spring 5个基础包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
  • 创建一个普通的类
public class User {
    public void add(){
        System.out.println("add方法执行了....");
    }
}
  • 创建配置文件bean.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="user" class="com.springDemo.User"/>
</beans>
  • IOC底层实现(重点)
public class SpringDemo {
    @Test
    public void test(){
        //利用IOC工厂接口,加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //利用反射获取bean对象
        User user = context.getBean("user", User.class);
        user.add();
    }
}

结论

  • 实现IOC容器有两个接口
    • BeanFactory : 只有在获取bean时才会创建对象,不推荐使用;
    • ApplicationContext : 是前者的子接口,功能更强大,在加载配置文件时就已经创建完所有对象,加快了响应时间,推荐使用;

Bean的依赖注入

依赖注入又称DI,作用就是给bean注入属性

基础依赖注入(xml方式)

  • 方式一: set注入
//创建user实体类,附属set方法
public class User {

   private String name;
   private String age;

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

    public void setAge(String age) {
        this.age = age;
    }
}
<bean id="user" class="com.springDemo.User">
    <!--使用property标签给属性赋值-->
    <property name="name" value="张三"></property>
    <property name="age" value="18"></property>
</bean>

  • 方式二: 有参构造注入
public class User {
    
   private String name;
   private String age;
	//创建user类的有参构造方法
    public User(String name, String age) {
        this.name = name;
        this.age = age;
    }
}
<bean id="user" class="com.springDemo.User">
        <!--使用constructor-arg标签给有参构造赋值-->
    <constructor-arg name="name" value="张三"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
</bean>

注入外部bean

public interface UserDao {
    public void update();
}
public class UserDaoImpl implements UserDao {
    @Override
    public void update() {
        System.out.println("UserDao update....");
    }
}
public class UserService {

    //创建UserDao类型的属性,生成set方法
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
<bean id="userService" class="com.example.service.UserService">
    <!--注入userDao对象-->
    <!--name是userService类里的属性名称-->
    <!--ref是userDao创建的bean的id值-->
    <property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.example.dao.impl.UserDaoImpl"></bean>

注入内部bean

//部门类
public class Dept {
    private String dname;

    public void setDname(String dname) {
        this.dname = dname;
    }
}
//员工类
public class Emp {
    private String ename;
    private String gender;

    //员工属于某一个部门
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
<bean id="emp" class="com.example.domain.Emp">
    <!--设置普通属性-->
    <property name="ename" value="张三"></property>
    <property name="gender" value=""></property>
    <!--设置对象内部属性-->
    <property name="dept">
        <bean id="dept" class="com.example.domain.Dept">
            <property name="dname" value="财务部"></property>
        </bean>
    </property>
</bean>

注入集合类型属性

public class Student {

    private String[] arr;
    private List<String> list;
    private Map<String,String> map;

    public void setArr(String[] arr) {
        this.arr = arr;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
}
<bean id="student" class="com.collection.Student">
      <!--数组类型注入-->
      <property name="arr">
          <array>
              <value>语文</value>
              <value>数学</value>
          </array>
      </property>

      <!--list类型注入-->
      <property name="list">
          <list>
              <value>张三</value>
              <value>李四</value>
              <value>王五</value>
          </list>
      </property>

      <!--map类型注入-->
      <property name="map">
          <map>
              <entry key="JAVA" value="java"></entry>
              <entry key="PHP" value="php"></entry>
          </map>
      </property>
  </bean>

Bean标签的基本配置

id:唯一标识,可以取任意名称,但必须唯一;
class:实现类的全限定名称;

scope:对象的作用范围;在这里插入图片描述

当scope的的取值范围为:singleton
Bean的实例化个数为:1个
Bean的实例化时机:当加载Spring配置文件时,实例化配置中的Bean
Bean的生命周期:

  • 对象创建,当应用加载,创建容器时,对象就被创建了;
  • 对象运行,只要容器在,对象一直活着;
  • 对象销毁,随着容器销毁一起销毁;

当scope的的取值范围为:prototype
Bean的实例化个数为:多个
Bean的实例化时机:每当调用getBean()方法时都会实例化一次Bean;
Bean的生命周期:

  • 对象创建,调用getBean()方法时都会实例化一次Bean;
  • 对象运行,只要对象在使用中,就会一直存活;
  • 对象销毁,长时间未使用会被垃圾回收器回收;
Bean生命周期配置;
  • init-method:指定类中的初始化方法的名称;
  • destroy-method:指定类中的销毁方法名称;

基于注解方式实现对象创建

  • @Conponent
  • @Service
  • @Controller
  • @Repository

这四个注解功能都是一样的,都是为了创建对象,不同的层放不同的注解方便辨识;

组件扫描配置

使用注解必须写好组件扫描配置,以下介绍几种常用配置;

  • 基础配置及案例
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">


		<!--扫描包上层目录,-->
		<context:component-scan base-package="com.demo"/>
</beans>
/**
 * 注解内不写value值的话会默认
 * 使用类名的首字母小写作为值
 */
@Component("userDao")
public class UserDao {
    public void add(){
        System.out.println("userDao add...");
    }
}
    @Test
    public void test(){
    //测试案例,成功调用
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        userDao.add();
    }
  • 进阶组件配置
    <!--use-default-filters不配置默认扫描com.demo下全部目录-->
    <context:component-scan base-package="com.demo" use-default-filters="false">
        <!--include-filter意思是扫描哪些内容-->
        <!--整个配置是说扫描com.demo下所有带Controller注解的类-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <context:component-scan base-package="com.demo" >
        <!--exclude-filter意思是不扫描哪些内容-->
        <!--整个配置是说扫描com.demo下除了Controller注解的其他类-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

基于注解方式实现属性注入

  • @AutoWired

根据属性类型进行自动注入

    <context:component-scan base-package="com.demo" />
/**
*创建UserDao接口,UserDaoImpl 实现接口
*加上@Repository注解
*/
@Repository
public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("UserDao add ...");
    }
}
/** 
创建UserService类加上@Service注解
并在UserService类中定义UserDao类型属性并加上@Autowired注解进行自动注入
*/
@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    public void add(){
        System.out.println("service add...");
        userDao.add();
    }
}
//测试类
@Test
public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}
  • @Qualifier

根据属性名称进行自动注入
需要跟@Autowired一起使用,一个接口可以有多个实现类,不知道用哪个时,可以使用@Qualifier指定

@Repository(value = "userDaoA")
public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("UserDao add ...");
    }
}
@Service
public class UserService {
    @Autowired
    @Qualifier(value = "userDaoA")
    private UserDao userDao;
}
  • @Resource

可以根据类型注入也可以根据名称注入,因为是javax扩展包的注解,所以spring官方不建议使用

@Repository(value = "userDaoA")
public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("UserDao add ...");
    }
}
@Service
public class UserService {
    //根据类型注入
    //@Resource
    //根据名称注入
    @Resource(name = "userDaoA")
    private UserDao userDao;
    private UserDao userDao;
}
  • @Value

注入普通类型属性

    @Value("abc")
    private String name;

完全注解开发

就是指删除xml配置,创建一个SpringConfig对象来代替xml配置,同时测试类的ApplicationContext实现类也需要变更为AnnotationConfigApplicationContext,实际开发中一般使用spring boot方式;

//@Configuration是指代替xml配置
//ComponentScan配置扫描路径
@Configuration
@ComponentScan(basePackages = {"com.demo"})
public class SpringConfig {

}
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值