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();
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值