• 1.spring基础知识讲解


    引言:以下记录一些自己在使用时pringle框架时的一些自己心得合成体会时,如有侵权,请联系本博主。

    1. spring基本都使用

    spring是一个开源的轻量级框架,其目的是用于简化企业级应用程序开发,降低侵入性;

    spring提供的IOC和AOP功能,可以将组件的耦合度降至最低,便于系统日后的维护和升级。

    在spring中,任何的java类和JavaBean都被当成Bean处理,这些Bean通过容器管理和使用。

    1.1 最基本的spring的使用

    spring容器有BeanFactory和ApplicationContext两种类型,ApplicationContext接口继承自BeanFactory接口,拥有更多的

    企业级方法,推荐使用该类型。 ClassPathXmlApplicationContext是ApplicationContext的一个实现类。

    (1) spring容器实例化:创建spring的IOC容器对象

    @Test
    //测试使用无参构造器创建对象
    public void test1(){
        //启动spring容器
        ApplicationContext ac=new ClassPathXmlApplicationContext("config/basic.xml");
        //调用容器的方法来获取对象
        //方法的返回值类型是object,所以要强转,或者调用重载的方法(多传一个参数),
        //反射,这是一个class对象,告诉它返回类型.
        ExampleBean eb=ac.getBean("eb",ExampleBean.class);
        System.out.println(eb);
    }

     说明:参数值config/basic.xml是spring配置文件的位置

    (2) bean的实例化:在创建spring的IOC容器对象的时候,它会调用basic.xml中配置的bean(HelloWorld)的构造器进行初始化,

    同时会调用属性的set方法对属性进行赋值();

    <!-- 使用无参构造器创建对象 :告诉容器你要创建哪个对象-->
    <!--   id 属性:bean的名称,要求唯一。
         class属性:bean的完整的类名(要求包含包名)。 -->
     
    <bean id="eb" class="basic.ExampleBean"/> <!-- 这里写的是包含ExampleBean类的那个包名 -->

    java类ExampleBean如下:

    package basic;
    
    public class ExampleBean {
    
        public ExampleBean() {
            System.out.println("ExampleBean's 无参构造");
            
        }
    
    }

     除了使用构造器来实例化对象(主要方式),还可以使用以下两种方式来实例化对象(了解):

    <!-- 使用静态工厂的方法创建对象 -->
    <!-- factory-method属性:指定一个静态方法 
        注:spring容器会调用指定静态方法来创建对象 -->
    <bean id="cal" class="java.util.Calendar" factory-method="getInstance"/>
    
    <!-- 使用实例工厂方法创建对象 -->
    <!-- factory-bean属性:某个bean的id。
         factory-method属性:指定一个实例方法。 -->
    <bean id="date1" factory-bean="cal" factory-method="getTime"/>
    View Code

    1.2 bean的作用域、生命周期以及延迟实例化

    <!-- 配置作用域 -->
    <!-- scope属性:默认值是singleton(单例,即容器针对一个bean的配置,只会创建一个实例)。
        如果值是prototype(原型,会创建多个实例)-->
    <bean id="stu1" class="basic.Student" scope="prototype"/>
    
    <!-- 配置生命周期相关的两个方法 -->    
    <!-- init-method属性:初始化方法名 
         destroy-method属性:销毁方法的名称,只有作用域为单例的bean,销毁方法才会执行-->    
    <bean id="mb1" class="basic.MessageBean" init-method="init"
     destroy-method="destroy" /><!-- 告诉容器要销毁哪个方法 -->
    
    <!-- 配置延迟加载 -->
    <!-- 默认情况下,当spring容器启动之后,会将所有作用域为当例(singleton)先创建好 -->
    <bean id="lz1" class="basic.LazyBean" lazy-init="true"/>
    
    <!-- 将以上几种配置合成 -->
    <bean id="mb2" class="basic.MessageBean1" init-method="init" 
        destroy-method="destroy" scope="singleton" lazy-init="false"/>
    View Code
    @Test
        public void test1(){
            ApplicationContext ac=new ClassPathXmlApplicationContext("config/basic2.xml");
        Student stu1=ac.getBean("stu1",Student.class);
        Student stu2=ac.getBean("stu1",Student.class);
        //默认情况下,对于一个bean的配置,容器只会创建一个对象(即作用域为singleton).
        System.out.println(stu1==stu2);
    }
    
    @Test
    //测试生命周期
    public void test2(){
        //启动spring容器
        //ApplicationContext这个接口没有定义关闭容器的方法,所以需要用其子接口。
        //AbstractApplicationContext这是ApplicationContext子接口,里面有关闭的方法。
        AbstractApplicationContext ac=new ClassPathXmlApplicationContext("config/basic2.xml");
        //通过容器获得对象
        MessageBean mb1=ac.getBean("mb1",MessageBean.class);
        //调用对象的方 法
        mb1.sendMsg();
        //首先要先关闭容器,才销毁
        ac.close();
    }
    
    @Test
    //测试 延迟加载
    public void test3(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("config/basic2.xml");
        // 默认情况下,当spring容器启动之后,会将所有作用域为当例(singleton)先创建好
    }
    
    @Test
    //多种配置合成在一起
    public void test4(){
        AbstractApplicationContext ac=new ClassPathXmlApplicationContext("config/basic2.xml");
        MessageBean1 mb2=ac.getBean("mb2",MessageBean1.class);
        mb2.sendMsg();
        ac.close();
    }
    View Code
    package basic;
    
    public class Student {
    
        public Student() {
            System.out.println("Student 无参构造");
        }
        
    }
    
    public class LazyBean {
        public LazyBean() {
            System.out.println("实例化:LazyBean()");
        }
    }
    
    public class MessageBean {
        
        public MessageBean() {
            System.out.println("实例化:MessageBean()");
        }
        
        public void init(){
            System.out.println("初始化:init()");//表示获取一些资源
        }
        
        public void sendMsg(){
            System.out.println("调用方法:sendMsg()");
        }
        
        public void destroy(){
            System.out.println("销毁:destroy()");
        }
    }
    public class MessageBean1 {
    
        public MessageBean1() {
            System.out.println("实例化:MessageBean1()");
        }
        public void init(){
            System.out.println("初始化:init()");
        }
        public void sendMsg(){
            System.out.println("调用方法:sendMsg()");
        }
        public void destroy(){
            System.out.println("销毁方法:destroy()");
        }
    }
    View Code

    2. IOC (Inversion of Control,控制反转)

    IOC是指程序中对象的获取方式发生了反转,由最初的new方式创建,转变为由第三方框架(spring)创建,

    注入(DI),它降低了对象之间的耦合度。spring容器是采用了DI方式实现方法了IOC空字符串,IOC是spring框架的基础和核心。

    2.1 DI

    DI:依赖注入(Dependency Injection)的基本原理就是将一起工作具有关系运算符的对象添加,通过

           构造方法参数或方法参数传入建立关联,因此容器的工作就是创建bean时注入那些依赖关系

    IOC是一种思想,而DI是实现IOC的主要技术途径。

     DI主要有两种注入方式:Setter注入和构造器注入。

    (1) Setter注入

    通过调用无参构造器或无参static工厂方法实例化bean以后调用该bean的setter()方法,即可实现setter方式的注入.

    property属性表示采用set方式注入,既然是注入,那肯定是发生在两个组件(对象)之间。

    方法一:直接注入值(value)

    <bean id="computer" class="com.bean.Computer">
        <property name="mainboard" value="技嘉"/>
    </bean>
    public class Computer{
        private String mainboard; // 主板
        public String getMainboard(){
            return mainboard;
        }
        public void setMainboard(String mainboard){
            this.mainboard = mainboard;
        }
    }

    方法二:引用的方式(ref),ref主要用户引用对象

    <!-- 告诉spring采用无参构造器的方法创建对象B对象 -->
    <bean id="b1" class="ioc.B"/>
    <bean id="c1" class="ioc.C"/>
    
    <!-- 配置依赖注入(采用set方法) -->
    <!-- property属性:表示采用set方法来注入。name属性用来指定属性名(首先首字母B大写,然后在前面加set),ref属性指定属性值 -->
    <bean id="a1" class="ioc.A">
        <!-- setB -->
        <property name="service" ref="c1"></property>
    </bean>

    测试set方式注入:

    @Test
    //测试set方法注入
    public void test5(){
        AbstractApplicationContext ac=new ClassPathXmlApplicationContext("config/ioc.xml");
        A a1=ac.getBean("a1",A.class);
        a1.execute();
    }
    View Code
    package ioc;
    
    import ioc.Service;
    
    public interface Service {
        public void f1();
    }
    
    public class B implements Service{
        public B(){
            System.out.println("B()");
        }
        public void f1(){
            System.out.println("B's f1()");
        }
    }
    
    public class C implements Service{
        public C(){
            System.out.println("C()");
        }
        public void f1(){
            System.out.println("C's f1()");
        }
    }
    
    public class A {
        private Service service;
        //容器调用对象提供的set方法来建立依赖关系
        //1.类应该提供有对应的set方法
        //2.在配置文件中,使用property元素来配置依赖关系
        
        public void setService(Service service) {
            System.out.println("setService()");
            this.service = service;
        }
    
        public A(){
            System.out.println("A()");
        }
    
        public void execute(){
            service.f1();
        }
    }
    View Code
    //执行结果
    B()
    C()
    A()
    setService()
    C's f1()
    View Code

    (2) 构造器注入(使用相对较少)

    基于构造器的注入是通过调用带参数的构造器来实现,容器在bean被实例化的时候,根据参数类型执行相应的构造器。

    构造器注入,可以强制给bean注入某些参数,比set注入更严格。

    构造器的注入一般格式为:

    方法一:直接注入值(value)

    按构造参数索引指定注入

    <bean id=''phone" class="com.bean.MobilePhone">
      <constructor-arg index="0"> value="ARM"/>        //当然这里也可以采用ref去引用另外的bean,但是采用ref的时候主要用于引用对象
      <constructor-arg index="1"> value="2G"/>
    </bean>
    public class MobilePhone{
      private String cpu;
      private String ram;
      //构造方法
      public MobilePhone(String cpu,String ram){
        this.cpu = cpu;
        this.ram = ram;
      }
    }

    方法二:采用引用的方式(ref)

    <!-- 配置依赖注入(采用构造器方式注入) -->
    <!-- index属性:指定参数的位置(从0开始). -->
    <bean id="wt1" class="ioc.Waiter" />
    <bean id="rest1" class="ioc.Restaurant" >
        <!-- 将ref传到构造方法的第一个参数上 -->
        <constructor-arg index="0" ref="wt1"></constructor-arg>
    </bean>
    View Code
    @Test
    //测试构造器注入
    public void test6(){
        AbstractApplicationContext ac=new ClassPathXmlApplicationContext("config/ioc.xml");
        Restaurant rest1=ac.getBean("rest1",Restaurant.class);
        System.out.println(rest1);
    }
    View Code
     1 package ioc;
     2 
     3 import ioc.Waiter;
     4 
     5 public class Waiter {
     6 
     7     public Waiter() {
     8         System.out.println("Waiter()");
     9     }
    10     
    11 }
    12 
    13 public class Restaurant {
    14     private Waiter wt;
    15     
    16     public Restaurant(){
    17         System.out.println("Restaurant()");
    18     }
    19     public Restaurant(Waiter wt) {
    20         System.out.println("Restaurant(wt)");
    21         this.wt = wt;
    22     }
    23     
    24     @Override
    25     public String toString() {
    26         return "Restaurant [wt=" + wt + "]";
    27     }
    28     
    29 }
    View Code
    //执行结果
    Waiter()
    Restaurant(wt)
    Restaurant [wt=ioc.Waiter@5f282abb]
    View Code

     2.2 自动装配 

    <bean id="wt1" class="ioc.Waiter"/>
    <!-- 自动装配 :默认情况下,容器禁止自动装配。-->
    <!-- (1)byName:以属性名(wt)作为bean的id,查找配置文件,找到之后,会使用set方法来注入。 
         注: 找不到会注入null值, 不会找到多个符合条件的bean。
         (2)byType:以属性类型(Waiter)作为bean的类型,查找配置文件(ioc.Waiter),找到之后,会使用set方法来注入。
         注:找不到会注入null值,如果找到多个符合条件的bean,会出错。
         (3)constructor:与byType类似,只不过会使用构造器来注入。     -->
    <bean id="rest" class="ioc.Restaurant" autowire="byType"/>
    @Test
    //测试自动装配
    public void test1(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
        Restaurant rest=ac.getBean("rest",Restaurant.class );
        System.out.println(rest);
    }
    View Code
     1 package ioc;
     2 
     3 public class Restaurant {
     4     private Waiter wt;
     5     public Restaurant(){
     6         System.out.println("构造:Restaurant()");
     7     }
     8 
     9     public void setWt(Waiter wt) {
    10         System.out.println("setWt()");
    11         this.wt = wt;
    12     }
    13 
    14     @Override
    15     public String toString() {
    16         return "Restaurant [wt=" + wt + "]";
    17     }
    18 }
    19 
    20 public class Waiter {
    21     public Waiter() {
    22         System.out.println("构造:Waiter()");
    23     }
    24 }
    View Code
  • 相关阅读:
    CentOS中的中文乱码问题的解决
    xml2config not found. Please check your libxml2 installation.
    yii数据库存储对象DAO
    linux常用svn命令
    通过rpm包安装、配置及卸载mysql的详细过程.
    php Undefined index和Undefined variable的解决方法
    【30篇突击 android】源码统计四
    【30篇突击 android】源码统计三
    Android 新手入门指导
    android 问题汇总系列之三
  • 原文地址:https://www.cnblogs.com/shiyun32/p/9351781.html
Copyright © 2020-2023  润新知