栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring(二)IoC控制反转

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring(二)IoC控制反转

一、概念

IoC:Inversion of Controller,即控制反转,不是一种技术,而是一种设计思想。

IoC是指在程序开发中,实例的创建不再由调用者管理,而是由spring容器管理。Spring容器负责控制程序之间的关系,而不是由程序代码直接控制。控制权由程序代码转移到了Spring容器,控制权发生了反转,这就是Spring的IoC思想。

二、案例 2.1、创建项目,添加pom依赖

        
        
            junit
            junit
            4.12
            test
        
        
        
            org.springframework
            spring-context
            5.2.8.RELEASE
        
    
    
        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    1.8
                    1.8
                
            
        
    
2.2、创建一个实体类
public class Team {

    private Integer id;
    private String name;
    private String location;

    public Team(){
        System.out.println("Team的默认构造方法被调用:id="+id+",name="+name+",location="+location);
    }
}

2.3、添加一个配置文件application.xml




    
    
    
    

2.4、获取Spring容器

Spring提供了两种容器,BeanFactory和ApplicationContext

2.4.1、BeanFactory

BeanFactory的基础类型是IoC容器,是管理Bean的工厂,它负责初始化各种Bean,并调用它们的生命周期方法。

BeanFactory接口有多个实现类,最常见的是org.springframework.beans.factory.xml.XmlBeanFactory,它是根据XML中的定义装配Bean。

创建对象时机:调用getBean时创建对象

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("application.xml"));
2.4.2、ApplicationContext

ApplicationContext是BeanFactory的子接口,也称为应用上下文。不仅提供了BeanFactory的所有功能,还添加了对i18n(国际化)、资源访问、事件传播等方面的良好支持。

创建对象时机:初始化applicationContext容器时

ApplicationContext接口的两个常用类:

ClassPathXmlApplicationContext,从类路径ClassPath中查找指定xml配置文件,找到后装载完成ApplicationContext的实例化。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");

FileSystemXmlApplicationContext,它与ClassPathXmlApplicationContext的区别在于:读取Spring配置文件时,FileSystemXmlApplicationContext不再从类路径中读取配置文件,而是通过参数指定配置文件位置,它可以获取类路径之外的资源,如:“D:application.xml”

ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("application.xml");
2.5、通过上下文获取容器中对象
    @Test
    public void test(){
        //使用spring容器创建对象
        //1、指定spring配置文件名称
        String springConfig="application.xml";
        //2、创建spring容器对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfig);
        //3、获取容器中的对象
        Team team1 = (Team) applicationContext.getBean("team1");
        //4、容器的其他API
        int count = applicationContext.getBeanDefinitionCount();
        System.out.println("容器中对象个数:"+count);
        String[] names = applicationContext.getBeanDefinitionNames();
        for(String name:names){
            System.out.println("容器中对象的名称:"+name);
        }
        //5、获取日期
        Date date = (Date) applicationContext.getBean("date");
        System.out.println("当前时间:"+date);
    }
三、Bean的标签属性
属性说明
class指定bean对应类的全路径
namebean对应对象的一个标识
scopebean对象的创建模式和生命周期,singleton和prototype
idbean对应对象的唯一标识,不能添加特别字符
lazy-init是否延迟加载,默认false。延迟加载,指对象被调用时才会加载,使用时需要通过getbean()方法获得对象。不延迟加载时,只需加载配置文件即可。
init-method加载配置文件即可进行的对象初始化的方法
destory-method对象销毁时调用方法

Team中补充方法:

    public void init(){
        System.out.println("初始化...");
    }

    public void destroy(){
        System.out.println("销毁...");
    }

application.xml中添加:

 
    
    

修改测试方法:

 @Test
    public void test(){
        //使用spring容器创建对象
        //1、指定spring配置文件名称
        String springConfig="application.xml";
        //2、创建spring容器对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(springConfig);
        System.out.println("----------容器初始化创建对象------------");
        //3、获取容器中的对象
        Team team1 = (Team) applicationContext.getBean("team1");
        Team team11 = (Team) applicationContext.getBean("team1");
        System.out.println(team1);
        System.out.println(team11);

        //4、容器的其他API
        int count = applicationContext.getBeanDefinitionCount();
        System.out.println("容器中对象个数:"+count);
        String[] names = applicationContext.getBeanDefinitionNames();
        for(String name:names){
            System.out.println("容器中对象的名称:"+name);
        }
        //5、获取日期
        Date date = (Date) applicationContext.getBean("date");
        System.out.println("当前时间:"+date);

        System.out.println("----------调用时创建对象------------");
        Team team2 = (Team) applicationContext.getBean("team2");
        Team team22 = (Team) applicationContext.getBean("team2");
        System.out.println(team2);
        System.out.println(team22);

        System.out.println("----------调用时创建对象:创建了多个对象------------");
        Team team3 = (Team) applicationContext.getBean("team3");
        Team team33 = (Team) applicationContext.getBean("team3");
        System.out.println(team2);
        System.out.println(team22);
        applicationContext.close();
    }

四、Spring容器创建对象方式

使用默认构造方法使用带参构造方法使用工厂类 4.1、创建实体类Team

public class Team {

    private Integer id;
    private String name;
    private String location;

    public Team(){
        System.out.println("Team的默认构造方法被调用:id="+id+",name="+name+",location="+location);
    }

    public Team(Integer id, String name, String location) {
        this.id = id;
        this.name = name;
        this.location = location;
        System.out.println("Team的全参数构造方法被调用:id="+id+",name="+name+",location="+location);
    } 
}
4.2、创建工厂类
public class MyFactory {

    public Team instanceFun(){
        System.out.println("MyFactory-------instanceFun");
        return new Team(1,"皇家马德里","马德里");
    }

    public static Team staticFun(){
        System.out.println("MyFactory-------staticFun");
        return new Team(2,"拜仁慕尼黑","慕尼黑");
    }

    
    public static void main(String[] args) {
        MyFactory myFactory=new MyFactory();
        Team team = myFactory.instanceFun();
        Team team1 = MyFactory.staticFun();
    } 
}
4.3、createType.xml




    
    
    
    
        
        
        
    
    
    
    
    
    


4.4、测试类
public class CreateType { 
    @Test
    public void test(){ 
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("createType.xml"); 
    } 
} 

运行结果:

五、基于XML的DI

DI-Dependency Injection,依赖注入。组件之间的依赖关系由容器在运行期间决定,即容器动态的将某个依赖关系注入到组件中。依赖注入的目的并非为软件系统带来更多的功能,而是提升组件重用频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要简单的配置,而无需任何代码就可以指定目标需要的资源,完成自身业务逻辑,不需要关系具体资源来于何处,由谁实现。

IoC是一种思想,一个概念,实现方式多种多样。依赖注入就是其中用的比较多的一种方式。

IoC和DI是同一个概念的不同角度描述。IoC是一个概念,一种思想,DI是实现它的手段。Spring框架使用依赖注入实现IoC。

Spring容器是一个超级大工厂,负责创建、管理所有java对象,这些java对象被称为bean。Spring容器管理着Bean之间的依赖关系(使用依赖注入方式),使用IoC实现对象之间解耦。

5.1、注入分类

bean实例再调用无参构造器创建对象后,就要对bean对象的属性进行初始化。初始化由容器自动完成,被称为注入。

5.1.1、通过set方法

set注入也称为设值注入,通过setter方法传入被调用者实例。这种方法简单直观,因而在Spring依赖注入中大量使用。

5.1.2、通过构造方法

构造注入:在构造调用者实例同时,完成被调用者实例化。使用构造器设置依赖关系。

5.1.3、自动注入

对于引用类型属性的注入,也可以不再配置文件中显示注入。可以通过为标签设置autowire属性值,为引用类型属性进行隐式注入(默认不自动注入引用类型属性)根据自动注入判断标准不同,可以分为:

byName:根据名称自动注入byType:根据类型自动注入

1、byName:当配置文件中被调用者bean的id与代码中调用者bean类属性名相同时,使用byName方式,让容器自动将被调用者bean注入给调用者bean。容器是通过调用者bean类属性名与配置文件中被调用者bean的id进行比较而实现自动注入的。

2、byType:要求配置文件中被调用者bean的class指定的类,要与代码中调用者bean类的某引用类型属性的类型同源。要么相同,要么is-a关系(子类或实现类)。但这样的同源的被调用bean只能有一个,超过一个会出现错误。

5.2、示例 5.2.1、创建TeamDao
public class TeamDao { 
    public void add(){
        System.out.println("TeamDao---------add");
    } 
}

5.2.2、创建TeamService
public class TeamService {

    private TeamDao teamDao; //=new TeamDao();

    public void add(){
        System.out.println("TeamService------------add");
        teamDao.add();
    }

    public TeamService() {
    }

    public TeamService(TeamDao teamDao) {
        this.teamDao = teamDao;
    }

    public void setTeamDao(TeamDao teamDao) {
        this.teamDao = teamDao;
    }
}
5.2.3、DI.xml



    

    
        
        
    

    
        
        
    

    
    

    
    


5.2.4、测试类
public class DITest {
    @Test
    public void test(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("DI.xml");
        TeamService teamService = (TeamService) applicationContext.getBean("teamService");
        teamService.add();

        TeamService teamService1 = (TeamService) applicationContext.getBean("teamService1");
        teamService1.add();

        TeamService teamService2 = (TeamService) applicationContext.getBean("teamService2");
        teamService2.add();

        TeamService teamService3 = (TeamService) applicationContext.getBean("teamService3");
        teamService3.add();
    }
}
六、基于注解实现IoC

对于DI使用注解,将不再需要在Spring配置文件中声明bean实例。Spring中使用注解,需要在原有Spring运行环境基础上做一些改变。

6.1、声明Bean的注解@Component

在类上添加注解@Component表示该类创建对象的权限交给Spring容器,注解的value属性用于指定bean的id值,可以省略。
@Component不指定value属性,bean的id是类名首字母小写。

//@Component标识在类上,表示该对象由Spring容器创建 value属性表示创建的id值,value可以省略,值也可以省略,默认为类名的首字母小写
@Component("teamDao")
//相当于xml配置文件中:
public class TeamDao {
    public void add() {
        System.out.println("TeamDao---------add");
    }

    public TeamDao() {
        System.out.println("TeamDao默认构造方法");
    }
}

@Component标识属于“万能”注解,Spring针对不同类型的类还提供了其他注解:

@Repository:用于dao实现类注解@Service:用于service实现类注解@Controller:用于controller实现类注解

@Repository、@Service、@Controller注解是对@Component注解的细化,标注数据持久层、业务实现层、访问控制层的注解。

@Repository
public class TeamDao {
    public void add() {
        System.out.println("TeamDao---------add");
    }

    public TeamDao() {
        System.out.println("TeamDao默认构造方法");
    }
}

@Service
public class TeamService {

    private TeamDao teamDao; //=new TeamDao();

    public void add(){
        System.out.println("TeamService------------add");
        teamDao.add();
    }

    public TeamService() {
    }

    public TeamService(TeamDao teamDao) {
        this.teamDao = teamDao;
    }

    public void setTeamDao(TeamDao teamDao) {
        this.teamDao = teamDao;
    }
}

@Controller
public class TeamController {

    public TeamController() {
        System.out.println("TeamController默认的构造方法");
    }
}
6.2、包扫描

需要在Spring配置文件中配置组件扫描器,用于指定在基本包中扫描注解。如果没有进行包扫描,添加的注解是不生效的。

多个包扫描方式:





    
    
    
    
    
    
    
    


6.3、属性注入@Value

在属性上使用注解@Value,该注解的value属性用于指定需要注入的值。使用该注解进行注入,类中无需setter方法;如果存在setter方法,注解添加到setter方法上也可以。

6.4、byType自动注入@Autowired

在引用属性上加@Autowired,该注解默认按使用类型进行装配Bean。使用该注解完成属性注入,类中无需setter。当然,若属性有setter,也可以将其加入到setter上。

6.5、byName自动注入@Autowired和@Qualifier

需要在属性上联合使用注解@Autowired和@Qualifier,@Qualifier的属性value用于指定要匹配的bean的id。类中无需setter方法,也可加到setter方法上。

@Autowired还有一个属性required,默认值为true,表示匹配失败后,会终止程序运行。若值为false,表示匹配失败后,将会忽略,未匹配值为null。

6.6、自动注入@Resource

jdk中提供了@Resource注解,该注解即可按照名称匹配Bean,也可以按照类型匹配Bean。 默认按照名称注入。 要求JDK6+ @Resource可以在属性上,也可以在set方法上。

6.6.1、byType注入引用类型属性

@Resource不带任何参数,默认按照名称的方式注入,按照名称不能注入再按照类型进行Bean匹配注入。

6.6.2、byName注入引用类型属性

@Resource指定其name属性,则按照name属性匹配Bean的id。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/703787.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号