java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring控制反转和依赖注入

Spring控制反转和依赖注入超详细讲解

作者:詩句☾⋆᭄南笙

控制反转(IoC)与依赖注入(DI)是密切相关的概念,它们通常一起出现在讨论Spring框架时,这篇文章主要介绍了Spring控制反转和依赖注入的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

概念

什么是 IoC

IoC(Inversion of Control),即控制反转,是一种设计原则,指的是将对象的创建、依赖关系的管理,从代码内部转移到外部容器(比如Spring容器)中去控制,从而让开发者不再手动管理这些依赖关系。

简单来说:

原本是由程序员主动控制去创建对象和管理依赖,现在这个控制权交给了Spring容器,由它来负责创建对象并注入依赖,这就是控制权的“反转”。

传统方式(没有IoC):

public class UserService {
    // 手动创建依赖对象
    private UserRepository userRepo = new UserRepositoryImpl(); 
}

使用IoC方式:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring");

什么是 DI

DI(Dependency Injection),即依赖注入,是 IoC 的一种实现方式

依赖注入是指:将对象所依赖的其他对象(依赖项),通过某种方式“注入”到该对象中,而不是由该对象自己去创建或查找这些依赖。

换句话说,DI 是 IoC 的具体技术手段,是 Spring 用来实现 IoC 的主要方法。

引入jar包

在pom.xml引入下面jar包

<properties>
    <spring.version>4.0.2.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- spring框架包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- lombok 可是省去pojo类中的get和set方法 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>

    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.2</version>
    </dependency>


  </dependencies>

引入maven后通过resources直接建立spring-config.xml文件

测试控制反转和依赖注入

在com.hz下建立HelloSpring类

@Data //注解实现get和set方法
public class HelloSpring {
    private String name;

    public void sayHello(){
        System.out.println("hello spring"+ name);
    }

}

在spring-config.xml下建立相应的bean

<!-- 创建一个 com.hz.HelloSpring类的实例,Bean 的 ID 是 helloSpring。-->
    <bean id="helloSpring" class="com.hz.HelloSpring">
        <!-- 给 com.hz.HelloSpring类下的属性为:name的赋值,值为value:lisi-->
        <property name="name" value="lisi"></property>
    </bean>

建立测试

public class HelloSpringTest {

    @Test
    public void sayHello() {
        //使用ClassPathXmlApplicationContext读取配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        //不是HelloSpring helloSpring = new HelloSpring()了
        HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring");

        helloSpring.sayHello();
    }
}

输出hello spring lisi

测试控制反转和依赖注入2

在com.hz.dao下建立UserDao接口

public interface UserDao {
    public int addUser();
}

在com.hz.dao.impl下建立UserDaoImpl类

public class UserDaoImpl implements UserDao {
    @Override
    public int addUser() {
        System.out.println("UserDaoImpl的addUser方法");
        return 0;
    }
}

在com.hz.service下建立UserService接口

public interface UserService {
    public int addUser();

}

在com.hz.service.impl下建立UserServiceImpl类

@Data
public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public int addUser() {
        return userDao.addUser();
    }
}

项目结构:

在spring-config.xml下建立相应的bean

<!--    Spring 会实例化一个 UserDaoImpl对象,并把它管理起来,你可以用 id "userDao"来引用它。-->
    <bean id="userDao" class="com.hz.dao.impl.UserDaoImpl"></bean>

    <bean id="userService" class="com.hz.service.impl.UserServiceImpl">
<!--        表示要给这个 UserServiceImpl对象中的名为 userDao的属性(通常是成员变量)注入一个值。
            注入的方式是通过 调用 setUserDao(...)方法(也就是 JavaBean 规范的 setter 方法),把一个引用类型的值传进去
      其中 name="userDao"→ 指的是目标 Bean 中的属性名(一般对应成员变量 private UserDao userDao;的字段名,且要求有对应的 setter 方法:setUserDao(...))
      其中 ref="userDao"→ 表示要注入的是另一个 Bean,这个 Bean 的 ID 是 "userDao"(也就是你在上面或别处定义的 com.hz.dao.impl.UserDaoImpl对象)
                     -->
        <property name="userDao" ref="userDao"></property>
    </bean>

建立测试

public class UserServiceImplTest {

    @Test
    public void addUser() {
        //使用ClassPathXmlApplicationContext读取配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        UserService userService = (UserService) context.getBean("userService");


        userService.addUser();
    }
}

使用注解实现Ioc和依赖注入

之前在spring-config.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"
       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.hz.dao,com.hz.service"/>

注解:

Spring IOC常用注解

@Component:实现Bean组件的定义

@Repository([实例化名称]) :用于标注DAO类

@Service([实例化名称]) :用于标注业务类

@Autowired+@Qualifier("userDao")等价于@Resource(name = "userDao")

Component和Repository与Service的作用相同,主要是为了区分dao包和service包

以示例2开启讲解

在原用的基础上改造com.hz.dao.impl下的UserDaoImpl类

@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public int addUser() {
        System.out.println("UserDaoImpl的addUser方法");
        return 0;
    }
}

@Repository("userDao")相当于:<bean id="userDao" class="com.hz.dao.impl.UserDaoImpl"></bean>

@Repository值是系统默认赋值,值为当前类的类名,首字母小写即userDaoImpl

在原用的基础上改造com.hz.service.impl下的UserServiceImpl类

@Service
@Data
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public int addUser() {
        return userDao.addUser();
    }
}

@Service和@Repository效果相同

@Autowired相当于

<bean id="userDao" class="com.hz.dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="com.hz.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>

下的<property name="userDao" ref="userDao"></property>,系统会自动赋值

建立测试

public class UserServiceImplTest {

    @Test
    public void addUser() {
        //使用ClassPathXmlApplicationContext读取配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService = (UserService) context.getBean("userServiceImpl");
        userService.addUser();
    }
}

输出:UserDaoImpl的addUser方法

总结

到此这篇关于Spring控制反转和依赖注入的文章就介绍到这了,更多相关Spring控制反转和依赖注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文