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的依赖:


    org.springframework
    spring-context
    5.2.6.RELEASE

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


        
            aliyun
            aliyun
            https://maven.aliyun.com/repository/public
        

1.1 配置applicationContext.xml文件

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

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

   


      
        
    

    

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配置:


        

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


    
        

(ii)


    
        

(iii)


    
        

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

(i)静态工厂

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

applicationContext.xml:


        

(ii)动态工厂

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

applicationContext.xml:


        

使用静态工厂时,直接写上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 myList;
    private Set mySet;
    private Map 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 myList) {
        this.myList = myList;
    }

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

    public void setMyMap(Map 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();
    }
}




    
        
            
                AAA
                BBB
                CCC
            
        

        
            
                AAA
                BBB
                CCC
            
        

        
            
                AAA
                BBB
                CCC
            
        

        
            
                
                
                    BB
                
            
        
        
            
                Aa
            
        
    

2.使用注解方式实现IOC


2.1 四种组件类型注解Spring系列学习之Spring IOC_第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 自动装配注解Spring系列学习之Spring IOC_第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 元数据注解

Spring系列学习之Spring IOC_第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


        
            org.springframework
            spring-context
            5.2.6.RELEASE
        

        
            org.springframework
            spring-test
            5.2.6.RELEASE
        

        
            junit
            junit
            4.12
        

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

你可能感兴趣的:(spring,java)