zoukankan      html  css  js  c++  java
  • Spring学习(四)

    Spring Ioc容器

    1、具有依赖注入功能的容器。负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。在Spring中BeanFactory是Ioc容器的实际代表者。BeanFactory接口提供了IoC容器的基本功能。Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中各个对象进行实例化及装配。

    Spring Ioc容器管理的对象:Bean

    1、定义

    • Bean就是由Spring容器初始化、装配及管理的对象,此外bean与应用程序中的其他对象没有什么区别.
    • Bean在容器内部由BeanDefinition对象表示。

    2、BeanDefinition

    • 全限定类名(FQN):用于定义Bean的实现类;(必须的)
    • Bean行为定义:包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
    • Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
    • Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,也就是依赖注入。

    3、Bean的作用域

    • “singleton”(单例,通过单例缓存池实现)
    • “prototype”(原型,每次创建全新的bean)
    • 另外提供“request”、“session”、“global session”三种web作用域

    Spring IoC容器创建Bean 的方式

    1、根据Bean定义里的配置元数据使用反射机制来创建Bean。

    • 使用构造
    • 静态工程方法
    • 实例工厂方法
    • 使用 FactoryBean 方式

    2、使用构造: 创建对象使用无参构造的方式,使用最多的一种方式,注入数据用setter 方法

    Fox类

    package ecut.ioc.creation;
    
    public class Fox {
        
        private String id ;
        
        private String name ;
        
        public Fox() {
            super();
            System.out.println( "Fox 无参构造" );
        }
        
        public Fox(String id , String name) {
            super();
            this.id = id;
            this.name = name;
            System.out.println( "Fox( String , String ) 构造" );
        }
        
        @Override
        public String toString() {
            return "Fox [id=" + id + ", name=" + name + "]";
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
        
    
    }

    constructor-creation.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-4.3.xsd">
    
         <!-- 调用无参构造 -->
        <bean id="fox1" class="ecut.ioc.creation.Fox" >
            <property name="id" value="A001" />
            <property name="name" value="苏妲己" />
        </bean>
        <!-- 使用名称调用有参构造 ,建议使用可读性好-->
        <bean id="fox2" class="ecut.ioc.creation.Fox" >
            <constructor-arg name="id" value="B001" />
            <constructor-arg name="name" value="雪山飞狐" />
        </bean>
        <!-- 使用索引调用有参构造 -->
        <bean id="fox3" class="ecut.ioc.creation.Fox" >
            <constructor-arg index="0" value="B002" />
            <constructor-arg index="1" value="旋涡鸣人" />
        </bean>
    </beans>

    测试类

    package ecut.ioc.creation;
    
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class BeanCreationByConstructor {
    
        public static void main(String[] args) {
            
            String configLocations = "classpath:ecut/**/constructor-creation.xml" ;
            
            AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
            
            //需要有无参构造,不然会抛出BeanCreationException,因为没有指定默认的构造函数
            Fox fox1 = container.getBean( "fox1" ,  Fox.class );
            System.out.println( fox1 );
            
            Fox fox2 = container.getBean( "fox2" ,  Fox.class );
            System.out.println( fox2 );
            
            Fox fox3 = container.getBean( "fox3" ,  Fox.class );
            System.out.println( fox3 );
            
            container.close();
            
        }
    
    }

    3、静态工程方法:某个类里面有一个方法专门用创建这个类的对象

    Sun类

    package ecut.ioc.creation;
    
    public class Sun {
        /*//"饿汉"式实现单例 
        private static final Sun SUN =new Sun();
        
        private Sun(){
            super();
            System.out.println( "构造方法执行" );
        }
        //调用getInstance()方法获取sun类型实例,调用类的静态方法是主动使用会导致 类被初始化
        public static Sun getInstance(){
            System.out.println( "使用静态方法返回 Sun 类型的实例" );
            //这个Sun 类型的实例是单例的
            return SUN ;
        }*/
    
        //懒汉式,线程安全实现单例 
        private static Sun SUN ;
        
        private Sun(){
            super();
            System.out.println( "构造方法执行" );
        }
        //调用getInstance()方法获取sun类型实例,调用类的静态方法是主动使用会导致 类被初始化
        public static Sun getInstance(){
            System.out.println( "使用静态方法返回 Sun 类型的实例" ); 
            //同步锁是类对应对象
            synchronized ( Sun.class ) {
                SUN = new Sun();
            }
            //这个Sun 类型的实例是单例的
            return SUN ;
        }
    
    }

    static-factory-method.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-4.3.xsd">
    
        <!-- factory-method指定的是静态方法,通过调用静态方法之前 -->
        <bean id="sun" 
                 class="ecut.ioc.creation.Sun"  
                 factory-method="getInstance" />
        
    </beans>

    测试类

    package ecut.ioc.creation;
    
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class BeanCreationByStaticFactory {
    
        public static void main(String[] args) {
            
            String configLocations = "classpath:ecut/**/static-factory-method.xml" ;
            
            AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
            
            System.out.println( "~~~~~~~~~~~~~~~~~" );
            //构造方法只执行一次,默认情况下,容器创建就已经创建了这个bean
            Sun s = container.getBean( "sun" ,  Sun.class );
            System.out.println( s );
            
            Sun x = container.getBean( "sun" ,  Sun.class );
            System.out.println( x );
            
            container.close();
            
        }
    
    }

    4、实例工厂方法:要有一个具体的工厂实例,有这个工厂实例去造bean

    Car类

    package ecut.ioc.creation;
    
    public class Car {
        
        private String brand ; // 品牌
        
        public Car(){
            super();
            System.out.println( "Car无惨构造执行" );
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
        
    }

    CarFactory类

    package ecut.ioc.creation;
    
    public class CarFactory {
        
        private String brandName ;
        
        public CarFactory() {
            super();
        }
    
        public CarFactory(String brandName) {
            super();
            this.brandName = brandName;
            System.out.println( "CarFactory( String ) 构造执行" );
        }
    
        public Car create(){
            System.out.println( "准备创建 Car 的实例" );
            Car c = new Car();
            c.setBrand( brandName );
            return c ;
        }
    
    }

    instance-factory-method.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-4.3.xsd">
    
    
        <!-- 先 创建 Car 工厂 -->
        <bean id="carFactory" class="ecut.ioc.creation.CarFactory" >
            <constructor-arg name="brandName" value="BYD" />
        </bean>
        
        <!-- 再 通过 工厂实例 ( carFactory ) 的 非静态方法来创建 Car -->
        <bean id="car" factory-bean="carFactory" factory-method="create" />
        
    </beans>

    测试类

    package ecut.ioc.creation;
    
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class BeanCreationByInstanceFactory {
    
        public static void main(String[] args) {
            
            String configLocations = "classpath:ecut/**/instance-factory-method.xml" ;
            
            AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
            
            System.out.println( "~~~~~~~~~~~~~~~~~" );
            
            Car c = container.getBean( "car" ,  Car.class );
            System.out.println( c.getBrand() );
            
            container.close();
            
        }
    
    }

    5、使用 FactoryBean 方式:FactoryBean 是一个接口,由FactoryBean类型的对象造另外一个对象

    DateFactoryBean

    package ecut.ioc.creation;
    
    import java.util.Calendar;
    import java.util.Date;
    
    import org.springframework.beans.factory.FactoryBean;
    //期望返回的类型xx,则xxFactoryBean implements FactoryBean<xx>
    public class DateFactoryBean implements FactoryBean<Date>{
        
        private int year ;
        private int month ;
        private int date ;
        private int hour ;
        private int minute ;
        private int second ;
        
        private static final Calendar CALENDAR = Calendar.getInstance();
        
        public DateFactoryBean(){
            super();
            System.out.println( "DateFactoryBean()" );
        }
    
        @Override
        public Date getObject() throws Exception {
            System.out.println( "准备获取 Date 类型实例" );
            CALENDAR.set( year, month - 1 , date , hour , minute , second );
            Date date = CALENDAR.getTime();
            return date ;
        }
    
        @Override
        public Class<?> getObjectType() {
            return Date.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    
    
        public int getYear() {
            return year;
        }
    
        public void setYear(int year) {
            this.year = year;
        }
    
        public int getMonth() {
            return month;
        }
    
        public void setMonth(int month) {
            this.month = month;
        }
    
        public int getDate() {
            return date;
        }
    
        public void setDate(int date) {
            this.date = date;
        }
    
        public int getHour() {
            return hour;
        }
    
        public void setHour(int hour) {
            this.hour = hour;
        }
    
        public int getMinute() {
            return minute;
        }
    
        public void setMinute(int minute) {
            this.minute = minute;
        }
    
        public int getSecond() {
            return second;
        }
    
        public void setSecond(int second) {
            this.second = second;
        }
    
        
    }

    约定:期望返回的类型xx,则xxFactoryBean implements FactoryBean<xx>

    factory-bean-creation.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-4.3.xsd">
    
        <!-- 以前: 指定 class 是什么类型,就返回什么类型的实例 -->
        <bean id="d" class="java.util.Date" />
        
        <!-- 以前: 指定 class 是什么类型,就返回什么类型的实例,且是使用无参构造 创建bean,则必须要有无参构造-->
        <bean id="fox1" class="ecut.ioc.creation.Fox" >
            <property name="id" value="A001" />
            <property name="name" value="苏妲己" />
        </bean>
        
        <!-- 这里: 指定的 class 是 XxxFactoryBean ,但是返回的却不是  XxxFactoryBean 类型的实例 -->
        <!-- 而是返回了  XxxFactoryBean 内部的 getObject 方法所返回的那个实例 -->
        <bean id="birthdate" class="ecut.ioc.creation.DateFactoryBean" >
            <property name="year" value="1997" />
            <property name="month" value="7" />
            <property name="date" value="1" />
            <property name="hour" value="12" />
            <property name="minute" value="30" />
            <property name="second" value="18" />
        </bean>
    
    </beans>

    测试类

    package ecut.ioc.creation;
    
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class BeanCreationByFactoryBean {
    
        public static void main(String[] args) {
            
            String configLocations = "classpath:ecut/**/factory-bean-creation.xml" ;
            
            AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
            
            Date d = container.getBean( "birthdate" ,  Date.class );
            System.out.println( d );
            
            DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
            
            System.out.println( df.format( d ) );
            
            container.close();
            
        }
    
    }

    转载请于明显处标明出处

    https://www.cnblogs.com/AmyZheng/p/9249550.html

  • 相关阅读:
    mac系统终端的color scheme配置和vim配置
    用子网掩码划分子网
    堆排序
    面试遇到两个稍显变态的题目,mark一下
    移动端适配的问题
    移动端click事件延时
    行内元素之间间距的产生与去除
    JS怎么判断一个对象是否为空
    Java面向对象基础
    Java中的final关键字
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9249550.html
Copyright © 2011-2022 走看看