IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring中IOC容器和DI属性注入学习详解 -> 正文阅读

[Java知识库]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);
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:30:08  更:2021-07-29 11:31:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年9日历 -2024/9/21 8:53:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码