zoukankan      html  css  js  c++  java
  • spring入门学习第一篇

    本篇知识点有:maven依赖,applicationContext.xml配置文件,Scope作用域,初始化和销毁,延时初始化lazy-init,工厂Factory,Aware接口,动态bean。内容可能过多,建议准备好瓜子可乐,不足之处,多多指正。

    1、maven依赖

      因为我们使用的是maven + spring-context学习的,所以在使用spring之前,我们要先把maven依赖导入进来,导入spring-context5.2.0.RELEASE版本。

      导入代码如下:

    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.2.0.RELEASE</version>
    </dependency>

    2、applicationContext.xml配置文件

      一般我们把这个配置文件命名为applicationContext_xxx.xml,xxx为功能

      在IDEA中,创建这个配置文件步骤:选择resources文件夹,右键--->new----->XML configuration File---->Spring Config

      这个配置里面一般是用来管理spring要管理的bean,注意:bean不能为接口或抽象类

      

    <?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">
    
    </beans>

    3、Spoce作用域

      spring2.0版本之前的版本作用域只有两种:prototype(原型)和singleton(单例)。

      spring2..0版本1之后新增了三种作用域:request(请求),session(会话),global session(Http Session作用域)。

      什么是作用域?

      通俗来说就是指定spring中管理的bean在什么时候生效,在什么范围内作用生效。

      下面一起来了解一下这些作用域的作用。

      1、prototype原型(又名 non-singleton非单例)

      每次getBean的时候都会重新new一个新的对象。

      2、singleton单例

      在spring容器创建的时候已经创建了bean对象,每次getBean的时候,会从容器中去获取bean对象,只会被创建一次,遵循单例模式。

      3、request请求

      在web环境下生效,被spring管理的bean,它的生存周期在一个完整的请求周期里面。

      4、session会话

      在web环境下生效,被spring管理的bean,它的生存周期在一个完整的session里面,session关闭或者程序结束的时候,它的生存周期也会结束,不同的人有不同的会话,互相不干扰。

      

    <?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">
        <!--scope设置这个bean的作用域-->
        <bean id="getEmp" scope="prototype" class="com.dao.EmpDao"/>
        
    </beans>

    4、初始化和销毁

      如何在bean的初始化之前或者销毁后做一些事情?

      spring提供了全局default-init-method,default-destroy-method和单个init-method,destroy-method

      

      1、全局初始化和销毁

      设置了全局初始化和销毁方法的bean,会在bean的创建和销毁时去bean中寻找init和destroy方法,并且调用此方法,如果没有,就不调用。

    <?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"
            default-init-method="init" default-destroy-method="destroy">
        
    </bean>

      2、单个初始化和销毁

      设置了单个初始化或销毁方法的bean,将覆盖掉全局的初始化和销毁方法。

    <?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"
            default-init-method="init" default-destroy-method="destroy">
        <bean id="getEmp" scope="singleton"         
               class="com.dao.EmpDao"
        init-method="init" destroy-method="destroy">
    
        </bean>
    
    </bean>    

    5、延时初始化lazy-init

      延时初始化只对Scope为singleton的对象有效,因为单例对象在容器加载时候就会创建,如果bean过多,就会造成资源负载,性能低,spring提供了一个lazy-init,设置为true的时候,容器启动时不会立即实例化bean对象,等到getBean时才实例化。

      1、全局延时加载

      

    <?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"
            default-init-method="true">
       
    </beans>

      2、单个延时加载

      和初始化销毁一样,设置了单个延时加载会将全局的覆盖掉。

    <?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"
    default-init-method="true">
      
    
        <bean id="getEmp" scope="singleton" class="com.dao.EmpDao"
        lazy-init="true">
    
        </bean>
    
    
    </beans>

    6、工厂Factory

      三种工厂实现:静态,实例,接口

      我们通过工厂AFactory类或者MyFactory将类A创建出来

      A类

    package com.dao;
    
    public class A {
    }

      AFactory类

    package com.dao;
    
    public class AFactory {
        private static A a = new A();
    
        //静态
        public static A createA(){
            return a;
        }
    
        //实例
        public A createA2(){
            return a;
        }
    }

      MyFactory类

    package com.dao;
    
    import org.springframework.beans.factory.FactoryBean;
    
    public class MyFactory implements FactoryBean<A> {
        //得到对象
        @Override
        public A getObject() throws Exception {
            return new A();
        }
        //得到bean类型
        @Override
        public Class<?> getObjectType() {
            return A.class;
        }
        //是否使用单例
        @Override
        public boolean isSingleton() {
            return true;
        }
    }

      xml配置

    <?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">
    <!--    静态,createA必须为静态方法-->
        <bean id="getA" class="com.dao.AFactory" factory-method="createA">
    
        </bean>
    
    <!--    实例-->
        <bean id="AFactory" class="com.dao.AFactory"></bean>
        <bean id="getA2" factory-bean="AFactory" factory-method="createA2"></bean>
    
    <!--    接口-->
        <bean id="getA3" class="com.dao.MyFactory"></bean>
    </beans>

    测试:

    package com.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestFactory {
        @Test
        public void test_AFactory(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Object obj1 = context.getBean("getA");
            Object obj2 = context.getBean("getA2");
            Object obj3 = context.getBean("getA3");
            System.out.println(obj1+"------getA");
            System.out.println(obj2+"------getA2");
            System.out.println(obj3+"------getA3");
        }
    }

    测试结果:

      因为使用单例作用域,所有第一个和第二个的对象是一样的。

      以上三种方法都能实现工厂模式创建出A类对象。

    7、Aware接口

      被spring管理的类实现Aware接口可以自动注入一些内容。

      

    package aware;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class SomeBean implements ApplicationContextAware, BeanNameAware {
        private ApplicationContext context;
        private String name;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.context = applicationContext;
        }
    
        public ApplicationContext getContext(){
            return this.context;
        }
    
        public String getName(){
            return this.name; 
        }
    
        @Override
        public void setBeanName(String name) {
            this.name = name;
        }
    }

      xml配置:

    <?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="someBean" class="aware.SomeBean"/>
    </beans>

      测试:

    package aware;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_aware.xml");
            SomeBean bean = context.getBean("someBean", SomeBean.class);
            ApplicationContext context2 = bean.getContext();
            String name = bean.getName();
            System.out.println(name);
            System.out.println(context == context2);
            //因为自动注入了一些内容,所有我们可以获取得到
        }
    }

    8、动态bean

    有些时候,我们不知道有什么bean是需要注册的,它是动态,不确定的,那么需要一个能够动态自动帮我们注册bean的方法

    package dynamic;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    
    public class DynamicRegistrator implements BeanFactoryAware {
        private  BeanFactory beanFactory ;
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
        }
    
        public <T> T register(String name,Class<T> clz,Object... args){
            // 通过传入一个bean类型来创建实体定义构造器对象,并且将实体类设置在里面的beanDefinition实体定义对象中的
            //beanClass中  ---beanClass为Object类型
            BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clz);
            //遍历我们传的参数,因为是可变参数,所以通过for循环遍历
            for (Object arg : args) {
                //使用实体定义构造器对象添加bean构造方法的参数,为什么构造参数能够完整无误的添加进来?
                //因为BeanDefinitionBuilder对象中有一个constructorArgIndex字段用来记录数,addConstructorArgValue方法
                // 每次添加一个参数constructorArgIndex就加一。
                definitionBuilder.addConstructorArgValue(args);
            }
            //通过getRawBeanDefinition获取原始实体定义方法获得一个beanDefinition实体定义类对象
            BeanDefinition definition = definitionBuilder.getRawBeanDefinition();
            //使用实体定义注册类.注册实体定义的方法,将准备注册的bean的自定义id名称,实体定义类对象实现注册
            //将beanFactory强转成BeanDefinitionRegistry接口类型,
            //然后使用BeanDefinitionRegistry注册实体对象定义的方法
            ((BeanDefinitionRegistry)beanFactory).registerBeanDefinition(name, definition);
            //注册完成,使用实体工厂的getBean返回一个实体对象
            return beanFactory.getBean(name, clz);
    
    //        流程:1、先创建一个实体定义构造器(并且将beanDefinition的beanClass设置为传过去的实体对象)
    //              2、添加构造方法的参数
    //              3、获取实体定义对象
    //              4、将实体定义对象和的bean的id注册
    //              5、返回需要的对象,因为已经注册过了,所以得到bean不会出错,实现了动态bean
    
        }
    }

      xml配置:

    <?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="registrator" class="dynamic.DynamicRegistrator" />
    </beans>

      使用:

    package dynamic;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            //得到容器对象
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_dynamic.xml");
            //得到动态记录类
            DynamicRegistrator registrator = context.getBean("registrator", DynamicRegistrator.class);
            //创建对象
            B b = registrator.register("b", B.class);
            System.out.println("-----debug: b = " + b);
            B b2 = context.getBean("b", B.class);
            System.out.println("-----debug: b2 = " + b2);
            System.out.println(b==b2);
        }
    }

      结束!

  • 相关阅读:
    swift关键字
    Swift开发注意点
    Mac上安装lua
    Runtime运行时机制
    ios开发中如何选择图片的加载方式
    ios开发中的静态内存分析
    loadrunner-2-9添加事务
    loadrunner-2-8HTML和URL模式
    loadrunner-2-7设置关联
    loadrunner中Windows Resource没有数据或不可用
  • 原文地址:https://www.cnblogs.com/liweixml/p/11695627.html
Copyright © 2011-2022 走看看