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

springIOC

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

springIOC

什么是Spring?

In a word:Spring是一个轻量级的控制反转(IoC-Inversion of Control)和

                                               面向切面(AOP-Aspect Oriented Programming)的容器(框架)。

   特点
(1)方便解耦,简化开发
  (2)Aop 编程支持
    (3)方便程序测试
      (4)方便和其他框架进行整合
         (5)方便进行事务操作
           (6)降低 API 开发

1. 体系结构  1.1 体系结构图

Spring框架至今已集成了20多个模块,这些模块分布在以下模块中:

核心容器(Core Container)数据访问/集成(Data Access/Integration)层Web层AOP(Aspect Oriented Programming)模块植入(Instrumentation)模块消息传输(Messaging)测试(Test)模块

1.2 核心容器(Core Container)

Spring的核心容器是其他模块建立的基础,有Spring-core、Spring-beans、Spring-context、Spring-context-support和Spring-expression(String表达式语言)等模块组成。

Spring-core模块:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)功能。Spring-beans模块:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。Spring-context模块:建立在Core和Beans模块的基础之上,提供一个框架式的对象访问方式,它以一种类似于 JNDI 注册的方式访问对象。是访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点。Spring-context-support模块:支持整合第三方库到Spring应用程序上下文,特别是用于高速缓存(EhCache、JCache)和任务调度(CommonJ、Quartz)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)的支持。Spring-expression模块:提供了强大的表达式语言去支持运行时查询和操作对象图。这是对JSP2.1规范中规定的统一表达式语言(Unified EL)的扩展。该语言支持set和get属性值、属性分配、方法调用、访问数组、集合和索引器的内容、逻辑和算术运算、变量命名以及通过Spring的IOC容器中以名称检索对象。它还支持列表投影、选择以及常用的列表聚合。

依赖图

                                                                         依赖图1.2.1

 

                                                                 依赖图1.2.2                 

        

                                                             实例依赖图1.2.3

注:其中spring框架不知道aop是注解方式中必须加的一个依赖

 1.3 Spring 配置文件

--》applicationContext.xml 

1.2.1 控制反转和依赖注入(IOC-DI) 

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。DL

依赖注入(DI),是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。

  • 依赖 : 指Bean对象的创建依赖于Spring容器
  • 注入 : 指Bean对象的属性(例如pojo类对象属性、其它需要依赖的Bean对象) , 由容器来设置和装配.

    传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;

    IOC是由专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建,程序被动接受对象,这就叫控制反转:将对象的创建权反转给(交给)Spring

    在Spring中,我们可以把IOC容器与Spring容器等同于一个东西,及IOC容器=Spring容器,我们也可以把Spring容器看做配置文件xxx.xml来简单记忆

    容器:一个Java 所编写的程序,可以管理对象的生命周期、对象与对象之间的依赖关系,在启动容器之后,所有的对象都可以直接取用,可以直接产生对象,或是建立对象与对象之间的依赖关系(不用编写任何程序代码)。

    (注::框架:是开发程序的一部分,没有框架是必须存在的。)

    IOC -- Inverse of Control,   控制反转,将对象的创建权反转给Spring!!DI -- Dependency Injection,依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!IoC的技术实现

    DI和IOC的关系: DI不能单独存在,DI需要在IOC的基础上来完成. 

    这样做得好处:做到了单一职责,并且提高了复用性,解耦了之后,任你如何实现,使用接口的引用调用的方法,永远不需要改变

     解耦

     以下是一个使用xml配置文件实现IOC的图例:


    1.2.2 DI:给属性赋值

    spring调用类的无参构造方法,创建对象。对象创建后给属性赋值。

    给属性赋值可以使用

    1)xml配置文件中的标签和属性;

    2)使用注解。

    DI分类 :1 set注入,也叫设值注入;

                    2 构造注入。

    package com.bjpowernode;
    
    import com.bjpowernode.service.SomeService;
    import com.bjpowernode.service.impl.SomeServiceImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AppMain {
        public static void main(String[] args) {
    //        SomeService service = new SomeServiceImpl();
    //        service.doSome();
            //1.指定spring配置文件:从类路径(classpath)之下开始的路径
            String config="beans.xml";
            //2.创建容器对象。 ApplicationContext 表示spring容器对象。通过ctx来获取某个java对象
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
            //这是个接口 然后通过这个实现类ClassPathXmlApplicationContext的构造方法中负责读这个配置文件 当遇到bean标签后 就创建对象 从这个类路径下寻找这个内容
            //3.从容器中获取指定名称的对象 使用getBean方法 //又因为是SomeService接口类型的对象所以还要转一下
            SomeService service = (SomeService) ctx.getBean("someService");
            //拿到这个someservice对象然后用其方法
            //4.调用对象的方法,接口的方法
            service.doSome();
    
        }
    }
    
    package com.bjpowernode.service;
    
    public interface SomeService {
        void doSome();
    }
    

    package com.bjpowernode.service;
    
    public class OtherService {
        public void doOther(){
            System.out.println("执行otherService的doOther()");
        }
    }
    

    resources下配置文件

    
    
    
        
        
        
    
        
        
        
    
    

    测试文件 

    package com.bjpowernode;
    
    import com.bjpowernode.service.OtherService;
    import com.bjpowernode.service.SomeService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.Date;
    
    
    public class Mytest {
        
        @Test
        public void test01(){
            //1.先指定配置文件路径
            String config="beans.xml";
            //2.创建容器对象
            //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
    //        SomeService service = ctx.getBean(SomeService.class);
    //        service.doSome();
            SomeService service=(SomeService)ctx.getBean("someService");
            service.doSome();
        }
    
    
    
    
        
        @Test
        public void test02(){
            //1.先指定配置文件路径
            String config="beans.xml";
            //2.创建容器对象
            //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
    //        SomeService service=(SomeService)ctx.getBean("someService");
    //        service.doSome();
        }
    
        @Test
        public void test03(){
             //1.先指定配置文件路径
             String config="beans.xml";
            //2.创建容器对象
            //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
    //         SomeService service=(SomeService)ctx.getBean("someService");
    //        service.doSome();
    }
        
        @Test
        public void test04(){
            String config="beans.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
            //获取容器中定义对象的数量
            int nums = ctx.getBeanDefinitionCount();
            System.out.println("容器中定义对象的数量=="+nums);
    
            //获取容器中定义的对象名称
            String names[] = ctx.getBeanDefinitionNames();
            for(String name:names){
                System.out.println("容器中对象的名称=="+name);
            }
    //         new java.util.Date();
        }
    //    让spring创建非自定义类的对象
    //    有class就能让spring创建对象
        @Test
        public void test05() {
            //1.先指定配置文件路径
            String config = "beans.xml";
            //2.创建容器对象
            //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
           Date date =(Date) ctx.getBean("mydate");
            System.out.println("date=="+date);
    
    //        从容器中拿对象
    
           OtherService service =(OtherService) ctx.getBean("otherService");
           service.doOther();
        }
        }
    

    测试结果 解释 如下

     解释:spring默认使用无参构造方法,创建对象 若定义了有参一定要定义无参

            因为配置文件中有两个bean标签 

    
    

    所以创建了两个对象

    //2.创建容器对象
    //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件 把对象创建出来
    ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

    实现类 

    package com.bjpowernode.service.impl;
    
    import com.bjpowernode.service.SomeService;
    
    public class SomeServiceImpl implements SomeService {
        
        public SomeServiceImpl(){
            System.out.println("SomeServiceImpl的无参数构造方法");
            //无参构造执行了说明对象创建了 意味着spring框架默认执行的是无参构造方法
        }
        @Override
        public void doSome(){
            System.out.println("执行了业务方法doSome");
        }
    }
    

    看注释无参构造执行了说明对象创建了  意味着spring框架默认执行的是无参构造方法

    SomeService service=(SomeService)ctx.getBean("someService");
    service.doSome();

    从容器中获取指定名称的对象,使用getBean()

    getBean(括号里是"引号中的是对象的名字 也是就")

     spring在什么时候创建对象?Test02
    创建spring容器对象的时候创建的,会读取配置文件,创建文件中声明的java对象。
    *    优点:获取对象速度快,因为对象已经创建好了
    *    缺点:占用内存
     spring容器创建对象 一次创建几个? Test03

    * 在创建容器对象时,会把配置文件中所有对象创建出来(spring默认规则)

    获取容器中对象的信息Test04  如图
     
     
        @Test
        public void test04(){
            String config="beans.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
            //获取容器中定义对象的数量
            int nums = ctx.getBeanDefinitionCount();
            System.out.println("容器中定义对象的数量=="+nums);
    
            //获取容器中定义的对象名称
            String names[] = ctx.getBeanDefinitionNames();
            for(String name:names){
                System.out.println("容器中对象的名称=="+name);
            }
    //         new java.util.Date();
        }

             控制台: 为什么输出前两行看实现类写了一个无参构造里sout

                     

    spring创建非自定义类的对象
    //    让spring创建非自定义类的对象
    //    有class就能让spring创建对象
        @Test
        public void test05() {
            //1.先指定配置文件路径
            String config = "beans.xml";
            //2.创建容器对象
            //ApplicationContext是个接口  用他的这个ClassPathXmlApplicationContext这个实现类  从类路径中来读取加载配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
           Date date =(Date) ctx.getBean("mydate");
            System.out.println("date=="+date);
    
    //        从容器中拿对象
    
           OtherService service =(OtherService) ctx.getBean("otherService");
           service.doOther();
        }

    Spring属性赋值的分类

     pojo类

    因为是set注入所以只要set方法就行

    package com.bjpowernode.ba01;
    
    public class Student {
        private String name;
        private int age;
    
        public Student() {
            System.out.println("Student无参数构造方法");
        }
    
    
    
        public void setName(String name) {
            System.out.println("setName=="+name);
            this.name ="Hello"+name;
        }
    
    
    
        public void setAge(int age) {
            System.out.println("setAge=="+age+"也就是先创建对象再进行set注入");
            this.age = age;
        }
        public void setEmail(String email){
    //        email属性 
            System.out.println("setEmail==="+email);
        }
        public void setGender(String gender){
            System.out.println("setGender=="+gender);
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + ''' +
                    ", age=" + age +
                    '}';
        }
    }
    

    配置文件 

    
    
    
        
        
        
        
            
            
            
            
        
        
        
            
        
    

    Test测试类

    package com.bjpowernode.ba01;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.Date;
    
    public class MyTest01 {
        @Test
        public void test01(){
            String config = "ba01/applicationContext.xml";
            ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
    
            Student student = (Student) ctx.getBean("myStudent");
            System.out.println("student=="+student);
            Date date = (Date) ctx.getBean("mydate");
            System.out.println("date=="+date);
        }
    }
    

    运行结果

     

     解释分析

    第一行是因为spring默认使用无参构造方法,创建对象

    第三行是因为spring和咱们约定的是只调用set方法 而set方法里由自己决定 我在里面加了一条sout如图b

    2-5行都是set注入

    第六行 在测试类中进行的输出 Hello李四是我在setName()方法中this.name=name;改成了

                                                                                                          this.name="Hello"+name;

    spring创建对象自动调用set方法 set方法里面的内容加不加都可以  在set代码里面可以对赋值进行改变加东西

    给属性赋值看得是set方法和有没有属性无关

    第七行是 给非自定义类属性赋值     只要能找到该class就可以对其在配置文件中配置然后进行赋值

                                                             

     

     

    前三行是因为 配置文件中有三个Bean标签需要创建三个对象 

     

     

      
        
        
            
            
        
     
        
        
        
        

     

                                                                    给引用类型赋值

     测试类

    byName()自动注入

    怎么实现的              按名称来进行比较来完成属性赋值

    String config="applicationContext,xml"

    当我们执行ApplicationContext ctx = new ClassPathXmlApplicationContext(config);时

    会去识别这个配置文件

    读到标签时先去创建这个对象 当看见autowire="byName"时会自动把 Student类中所有引用类型赋值 那么他就找这个类 找引用类型找School school 这个对象名字 找到之后 拿着这个名字和配置文件中的每一个标签的id比

    然后再给两个属性赋值

     byType()自动注入 

    怎么实现的              按类型来进行比较来完成属性赋值

    java类中引用类型的数据类型和spring容器中的bean的class值是同源关系的,这样的bean赋值给引用类型。                                 

       同源关系:
        1.java中引用类型的数据类型和bean的class值是一样的。
        2.java中引用类型的数据类型和bean的class值是父子类关系的。
        3.java中引用类型的数据类型和bean的class值是接口和实现类关系的。
           语法:
     
             简单类型属性赋值
             
    注意:在xml配置文件中,符合条件的对象,只能有一个。
    多余一个是报错的。

    然后再给两个属性赋值

    缺点:(引入注解的原因)

    一个大型项目中 应用多个配置文件 主要目的是 能够减小单一文件大小 让编写配置文件更多一点更方便

    2.2 基于注解的DI

    基于注解的DI:使用spring提供的注解,完成java对象创建,属性赋值。

    注解使用的核心步骤:

    1)在源代码中加入注解,eg:Component

    2)在spring的配置文件,加入组件扫描器的标签

    注解是对程序代码的一个说明

    1.创建对象的注解

    @Component

    @Respository

    @Service

    @Controller

    2.简单类型属性赋值

    @Value

    3.引用类型赋值

    @Autowired:Spring提供的注解,支持byName,byType

    @Autowired:默认是byType

    或者

    @AutoWired

    @Qualifier:使用byName

    @Resource:来自jdk中的注解,给引用类型赋值的,默认是byName

    @Resource:先使用byName,在byType

    若@Resource(name="bean的名称"):只能使用byName注入

    2.3IoC总结

    IoC:管理对象的,把对象放在容器中,创建,赋值,管理依赖关系。

    IoC:通过管理对象,实现解耦合。IoC解决处理业务逻辑对象之间的解耦合关系,也就是Servlet和dao之间的解耦合。

    spring作为容器管理什么对象?

    1) service对象,dao对象。

    2)工具类对象。

    不适合交给spring的对象?

    1)实体类

    2)servlet,listener,filter等web中的对象。他们上tomcat创建和管理的。

    代码和配置文件分离 若对象要调整只需该配置文件

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

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

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