搜索
简帛阁>技术文章>Spring系列学习之Spring IOC

Spring系列学习之Spring IOC

Spring IOC

Spring IOC的简单了解、使用。

目录

Spring IOC

一、Spring  IOC是什么?

二、实现SpringIOC的三种方式

三、使用步骤

1.使用XML实现SpringIOC

1.1 配置applicationContext.xml文件

1.2 配置程序入口Application类

1.3 使用XML实现IOC创建对象的三种方式

1.4 向IOC注入集合对象

2.使用注解方式实现IOC

2.1 四种组件类型注解​编辑

2.2 自动装配注解​编辑

2.3 元数据注解

3.使用JavaConfig的方式实现IOC

4.Spirng和JUnit4整合


一、Spring  IOC是什么?

IOC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。

传统的Java应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。

但是在Spring应用中,Java对象的创建控制权掌握在IOC容器中,当某个java 实例需要另一个java实例时,创建被调用者的工作不是由调用者实现,而是由spring容器来完成,然后注入调用者,因此称为依赖注入(Dependency Injection 简称 DI)。DI在Java中是通过反射技术实现的。

二、实现SpringIOC的三种方式

有三种实现SpringIOC的方式,为:

  1. 使用XML实现SpringIOC
  2. 使用注解方式实现SpringIOC
  3. 使用JavaConfig实现SpringIOC

三、使用步骤

1.使用XML实现SpringIOC

在maven中引入spingframework的依赖:

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

 如果网络不流畅,也可以同样在maven中配置aliyun的镜像仓库:

<repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
</repositories>

1.1 配置applicationContext.xml文件

在resources目录下创建applicationCont.xml配置文件。

在Spring官网找到Springframework的Core Technologies下拉找到配置文件的表头:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

1.2 配置程序入口Application类

在里面可以通过ClassPathXmlApplicationContext类来加载IOC中的bean

public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService.getUdao());
    }
}

1.3 使用XML实现IOC创建对象的三种方式

(1)通过无参的构造方法来创建,通过set方法注入属性

entity类代码如下:

public class User {
    public User() {
        System.out.println("User的无参构造方法");
    }
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public void show(){
        System.out.println("name="+name);
    }
}

applicationContext.xml配置:

<bean id="user" class="com.yygs.spring.entity.User">
        <property name="name"  value="张三"></property>
</bean>

(2)通过有参的构造方法来创建,不需要set方法

entity类

public class User {
    private String name;
    public User(String name) {
        this.name = name;
    }
    public void show(){
        System.out.println("name="+name);
    }
}

applicationContext.xml有三种写法,一般使用第二种。

(i)

<bean id="user" class="com.yygs.spring.entity.User">
    <!-- index指构造方法参数下标 -->
        <constructor-arg  index="0"  value="张三"></constructor-arg>
</bean>

(ii)

<bean id="user" class="com.yygs.spring.entity.User">
    <!-- name指参数名称 -->
        <constructor-arg  name="name"  value="李四"></constructor-arg>
</bean>

(iii)

<bean id="user" class="cn.sxt.vo.User">
    <!-- type指参数类型,一般情况下参数类型都不一样,如果一样,按顺序来 -->
        <constructor-arg  type="java.lang.String" value="李四"></constructor-arg>
</bean>

(3)通过工厂方法来创建对象,这种方法用的比较少。

(i)静态工厂

public class UserFactory {
    public static User  newInstance(String name){
        return  new User(name);
    }
}

applicationContext.xml:

<bean id="user" class=com.yygs.spring.factory.UserFactory"  factory-method="newInstance">
        <constructor-arg  index="0"  value="赵六"></constructor-arg>
</bean>

(ii)动态工厂

public class UserDynamicFactory {
    public  User  newInstance(String name){
        return  new User(name);
    }
}

applicationContext.xml:

<bean id="user" factory-bean="userFactory" factory-method="newInstance">
        <constructor-arg  index="0"  value="赵六"></constructor-arg>
</bean>
<bean id="userFactory"  class="com.yygs.spring.factory.UserDynamicFactory"/>

使用静态工厂时,直接写上class即可,因为调用的是类方法,与对象无关。

使用动态工厂时,需要先创建工厂对象再调用方法,所以需要先bean,再factory-bean引用。

1.4 向IOC注入集合对象

一般有Array,List,Set,Map,Props

package com.yygs.service;

public interface AccountService {
    public  void saveAccount();
}

package com.yygs.service.impl;

 import com.yygs.service.AccountService;
 import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;

 import java.util.*;

public class AccountServiceImpl implements AccountService {
    private String[] myStr;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;
    @Override
    public void saveAccount() {
        System.out.println(Arrays.toString(myStr));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }

    public void setMyStr(String[] myStr) {
        this.myStr = myStr;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

}

package com.yygs.ui;

import com.yygs.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService as = (AccountService)ac.getBean("accountService");
        as.saveAccount();
    }
}

<?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="accountService" class="com.yygs.service.impl.AccountServiceImpl">
        <property name="myStr">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>

        <property name="myList">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>

        <property name="mySet">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>

        <property name="myMap">
            <map>
                <entry key="A" value="AA"></entry>
                <entry key="B">
                    <value>BB</value>
                </entry>
            </map>
        </property>
        <property name="myProps">
            <props>
                <prop key="A">Aa</prop>
            </props>
        </property>
    </bean>
</beans>

2.使用注解方式实现IOC


2.1 四种组件类型注解

@Repository 注解:描述Dao类

//组件类型注解默认beanId为类名首字母小写
//beadId = userDao
@Repository
public class UserDao implements IUserDao{
    public UserDao(){
        System.out.println("正在创建UserDao:" + this);
    }
}

 @Service 注解:描述Service业务服务类

@Service
public class DepartmentService {

    @Resource
    private IUserDao udao;

    public void joinDepartment(){
        System.out.println(udao);
    }
}

@Controller 注解,描述控制类

@Controller
public class UserController {
}

@Component 注解,描述上面3种外的类,例如工具类

@Component("stringUtils")
public class StringUtils {
}

2.2 自动装配注解

 @Autowired 注解在set方法上,则自动按类型/名称对set方法参数进行注入。

@Autowired
    //如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入
    public void setUdao(UserDao udao) {
        System.out.println("setUdao:" + udao);
        this.udao = udao;
}

@Autowired 注解在属性上,IOC容器回自动通过反射技术将属性private修饰符自动修改成public,直接进行赋值。这是在运行时动态完成的。不需要依赖set方法,因此在日常开发中,一般将@Autowired注解放在属性上,而不用编写set方法。

@Service
public class UserService {

    //Spring IoC容器会自动通过反射技术将属性private修饰符自动改为public,直接进行赋值
    //不再执行set方法
    @Autowired
    private IUserDao udao ;

    public IUserDao getUdao() {
        return udao;
    }

}

@Autowired 注解的使用需要注意,IOC中不能有相同类型相同的2个bean,如下的UserDao以及UserOracleDao,解决办法是在某需要的类加上@Primary注解,或者去掉另一个不需要的类上的@Repository注解。

public interface IUserDao {
}


@Repository
public class UserDao implements IUserDao{
    public UserDao(){
        System.out.println("正在创建UserDao:" + this);
    }
}


@Repository
@Primary
public class UserOracleDao implements IUserDao {
    public UserOracleDao(){
        System.out.println("正在创建UserOracleDao:" + this);
    }
}

public class UserService {
    //注入IUserDao
    @Autowired
    private IUserDao udao ;

    public IUserDao getUdao() {
        return udao;
    }

}

@Resource 注解 在使用上,优先进行类名的匹配。没有匹配的类名则会进行类型进行匹配(同@Autowired)。

@Service
public class DepartmentService {
    /**
     * 1. @Resource设置name属性,则按name在IoC容器中将bean注入
     * 2. @Resource未设置name属性
     * 2.1 以属性名作为bean name在IoC容器中匹配bean,如有匹配则注入
     * 2.2 按属性名未匹配,则按类型进行匹配,同@Autowired,需加入@Primary解决类型冲突
     * 使用建议:在使用@Resource对象时推荐设置name或保证属性名与bean名称一致
     */
//    @Resource(name = "userDao")
//    private IUserDao udao;

    @Resource
    private IUserDao userOracledao; //规范化命名

    public void joinDepartment(){
        System.out.println(udao);
    }
}

2.3 元数据注解

 元数据注解一般配合配置文件。在resources目录下创建config.properties文件,文件内容为

metaData=baidu.com
connection.driver=xxxxx
connection.url=xxx
connection.username=xxx
connection.password=xxx

然后在类的属性上进行使用:

@Service
@Scope("prototype")//设置单例/多例,XML中 bean scope完全相同
public class UserService {
    @Value("${metaData}")//读取config.properties的metaData属性值
    private String metaData ;
    @Value("${connection.password}")
    private String password;

    public UserService(){
        System.out.println("正在创建UserService:" + this);
    }

    @PostConstruct //XML中bean init-method完全相同
    public void init(){
        System.out.println("初始化UserService对象,metaData=" + metaData);
    }

}

3.使用JavaConfig的方式实现IOC

@Configuration 标记配置类

JavaConfig实现IOC是去XML方式,通过给Bean设置@Configuration可以标记为一个配置类,相当于这个类为之前spring的xml。有这个类就可以删除之前的xml配置文件。

@Bean 
将类注入IOC容器

@ComponentScan 配置扫描包路径

通过给Bean添加@ComponentScan(basePackages="com.jony"),basePackages="com.jony"就是指定扫描包的路径,相当于我们之前使用的context:component-scan

@PropertySrouce 加载外部资源文件

通过@PropertySrouce可以加载我们在resource中的资源文件,相当于我们之前使用的context:property-placeholder


4.Spirng和JUnit4整合

1.maven工程依赖spring-test

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

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
</dependencies>

2.利用@RunWith@ContextConfiguration描述测试用例类

3.测试用例类从容器获取对象完成测试实例的执行

import com.imooc.spring.ioc.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

//将Junit4的执行权交由Spring Test,在测试用例执行前自动初始化IoC容器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringTestor {
    @Resource
    private UserService userService;

    @Test
    public void testUserService(){
        userService.createUser();
    }
}

一、概述IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象之间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IOC容器进行组装。在Sp
一,前言​本篇博客分享一些关于Spring中一个核心概念,IOC。​IOC:InversionofControl,控制反转。​通常情况下对于实例化一个对象,我们会通过关键字new创建出来。但是在实际项
IoC的全称是InversionofControl,中文称为控制反转,MartinFlower由根据它创造了一个新词:DependencyInjection,中文称为依赖注入。这两个词讲的是一回事儿
、浅谈IOCIOC(InversionofControl,控制反转)是spring的核心,贯穿始终。所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系:传
前言什么是SpringSpring是一个开源的免费的框架(容器)!Spring是一个轻量级的、非入侵式的框架!控制反转(IOC),面向切面编程(AOP)!支持事务的处理,对框架整合的支持!总结:S
前面两篇文章讲SpringIOC依赖注入和依赖查找的一些细节内容,那么无论是依赖注入还是依赖查找都有一个共同要涉及的问题就是依赖的来源。本文我们来聊下两种方式依赖的来源以及有什么不同以下是本篇文章讨论
1,SpringIOCIOCInversionofControl控制反转DI—DependencyInjection依赖注入控制反转和依赖注入实际表示的是同一种思想,由于控制反转概念比较含糊(可能只是
SpringIOC(InversionofControl,控制反转或依赖注入)1理解SpringIOCIOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优
IoC(InversionofControl),控制反转,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接控制。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制
学习Spring框架的人一定都会听过SpringIoC(控制反转)、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IOC、DI这两个概念是模糊不清的,是很难理解的,今天和大家分