spring框架学习之IOC

1 篇文章 0 订阅
1 篇文章 0 订阅

目录

 

一、什么是框架

二、什么是spring框架

三、IOC构造方法创建对象,注入参数,使用反射技术

四、工厂方法创建对象

五、对象的作用域和生命周期

六、Bean的后置处理器


一、什么是框架

高度抽取可重用代码的一种设计,也可以说是多个可重用模块的集合,形成一个某个领域的解决方案。

二、什么是spring框架

①开源框架

②简化企业级开发而生,EJB的升级

③IOC和AOP容器框架

④优良特性:

            1、非侵入式:不依赖于API,不需要理解API的每个类每个方法

            2、依赖注入

            3、面向切面编程

            4、容器

            5、组件化:把简单的组件配置组合成一个复杂的应用,在spring中可以使用xml和注解组合这些对象

            6、一站式:spring可以整合各种优秀的框架和第三方库

三、IOC构造方法创建对象,注入参数,使用反射技术

①获取容器

ApplicationContext: 就是 IOC 容器,通过下面两种方法获得

ClassPathXmlApplicationContext:xml 文件在类路径下
FileSystemXmlApplicationContext:xml 文件在磁盘路径下

②何时创建对象

// 无参构造函数 
public Person(){
        System.out.println("创建对象");
    }

// 注册组件
 <bean id="person01" class="cn.imooc.pojo.Person">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="11"></property>
        <property name="sex" value="男"></property>
        <property name="email" value="17521648152@163.com"></property>
 </bean>

// 测试
@Test
    public void test01(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
        // Person person =(Person) ioc.getBean("person01");
        // System.out.println(person);

    }

控制台打印结果
八月 14, 2019 10:01:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [ioc.xml]
创建对象

由上面的代码可知,启动容器的时候通过无参构造函数创建了对象,不是ioc.getBean("person01")创建对象,然后注入参数;也就是说容器创建完成的时候容器中的所有对象就已经创建好了,且对象时单实例的,如果没有这个组件,调用ioc.getBean("...."),则会报 notSuchBean 异常

③ 属性赋值

IOC容器在创建组件对象的时候,如果有无参构造器,<property>通过 setter 方法为 javaBean 的属性进行赋值;javaBean属性名由 getter/setter 方法决定的,即 set 后面的内容,首字母要小写

④ ioc.getBean( ) 获取对象的三种方式

​​​​​​​Person person =(Person) ioc.getBean("person01");
Person person = ioc.getBean(Person.class);
vPerson person011 = ioc.getBean("person01", Person.class);

如果一个类存在多个 JavaBean 对象,将会出现对象不唯一异常

⑤ 调用有参构造器进行对象创建并赋值

<bean id="person02" class="cn.imooc.pojo.Person">
        <constructor-arg name="name" value="lisi"></constructor-arg>
        <constructor-arg name="age" value="12"></constructor-arg>
    </bean>

不需要调用 setter 方法

⑥ 调用有参构造器不指定属性名

 <bean id="person03" class="cn.imooc.pojo.Person">
        <constructor-arg value="lisi"></constructor-arg>
        <constructor-arg value="12"></constructor-arg>
        <!--index 为参数指定索引位置,从0开始-->
        <constructor-arg value="17521648152@163.com" index="3"></constructor-arg>
        <constructor-arg value="男" index="2"></constructor-arg>
    </bean>

index 指定属性索引位置,从0开始

⑦ 重载的情况下用 type 指定参数的类型

    public Person(String name, Integer age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public Person(String name, String email, String sex) {
        this.name = name;
        this.email = email;
        this.sex = sex;
        
    }

    <bean id="person04" class="cn.imooc.pojo.Person">
        <constructor-arg value="lisi"></constructor-arg>
        <constructor-arg value="12" type="java.lang.Integer"></constructor-arg>
        <constructor-arg value="男"></constructor-arg>
    </bean>

    输出结果
    Person{name='lisi', age=12, sex='男', email='null'}

通过type指定的参数类型选择方法

⑧ P名称空间注入

<!--P名称空间注入-->
    <bean id="user01" class="cn.imooc.pojo.User" p:name="wangwu" p:age="11" p:sex="男"></bean>

⑨ 复杂类型注入

<!--复杂类型注入-->
    <bean id="student01" class="cn.imooc.pojo.Student">
        <!--数组注入-->
        <property name="strs">
            <array>
                <value>aaa</value>
                <value>bbb</value>
                <value>ccc</value>
            </array>
        </property>
        <!--list集合注入-->
        <property name="list">
            <list>
                <value>ddd</value>
                <value>eee</value>
                <value>fff</value>
            </list>
        </property>
        <!--set集合注入-->
        <property name="set">
            <set>
                <value>ggg</value>
                <value>hhh</value>
                <value>iii</value>
            </set>
        </property>
        <!--map集合注入-->
        <property name="map">
            <map>
                <entry key="name1" value="jjj"></entry>
                <entry key="name2" value="kkk"></entry>
                <entry key="name3" value="lll"></entry>
            </map>
        </property>
        <!--文件内容注入-->
        <property name="pro">
            <props>
                <prop key="name1">mmm</prop>
                <prop key="name2">nnn</prop>
                <prop key="name3">ooo</prop>
            </props>
        </property>
    </bean>

⑩ 设置参数为空

1、手动设置,对于字符串,整型是不一样的

    <bean id="user01" class="cn.imooc.pojo.User">
        <!--对于字符串设置<null/>-->
        <property name="name" ><null/></property>
        <!--对于Integer,设置value=""-->
        <property name="age" value=""></property>
        <!--对于字符串设置value="",是空字符串""-->
        <property name="sex" value=""></property>
    </bean>

    
    @Test
    public void test1(){
        User user01 =(User) ioc.getBean("user01");
        System.out.println(user01);
        // name为空
        System.out.println(user01.getName()==null);
        // age为空
        System.out.println(user01.getAge()==null);
        // sex不为空,为 ""
        System.out.println(user01.getSex()==null);
        System.out.println(user01.getSex().equals(""));
    }

    输出结果
    User{name='null', age=null, sex=''}
    true
    true
    false
    true

2、使用 set 构造方法注入时,如果没有写入参数,默认为 null;ref 引用外部 bean

    <!--给 car 注入参数-->
    <bean id="car01" class="cn.imooc.pojo.Car">
        <property name="carName" value="梅赛德斯"></property>
        <property name="price" value="1000"></property>
        <property name="color" value="blue"></property>
    </bean>

    <bean id="user02" class="cn.imooc.pojo.User">
        <property name="name" value="lisi"></property>
        <!--ref代表引入另外一个组件-->
        <property name="car" ref="car01"></property>
    </bean>
    
    @Test
    public void test2(){
        User user02 = ioc.getBean("user02", User.class);
        System.out.println(user02.getSex()==null);
        System.out.println(user02);
    }
    
    输出结果
    true
    User{name='lisi', age=null, sex='null', car=Car{carName='梅赛德斯', price=1000,             color='blue'}}

⑪ 引用内部 bean

    <bean id="user03" class="cn.imooc.pojo.User">
        <property name="name" value="lisi"></property>
        <!--引用内部 bin-->
        <property name="car">
            <bean class="cn.imooc.pojo.Car">
                <property name="carName" value="丰田"></property>
            </bean>
        </property>
    </bean>

⑫  util 名称空间创建集合类型的 bean ,方便其它bean引用

    <!--相当于 new linkedHashMap<>()-->
    <util:map id="myMap">
        <entry key="name1" value="jjj"></entry>
        <entry key="name2" value="kkk"></entry>
        <entry key="name3" value="lll"></entry>
    </util:map>

    <!--引用 myMap-->
    <bean id="student01" class="cn.imooc.pojo.Student">
        <property name="map" ref="myMap"></property>
    </bean>

<util:map>,<util:list> , <util:set>等等

⑬  级联属性:属性的属性

    public class User {

    private String name;
    private Integer age;
    private String sex;
    private Car car;
    ......

    }

    public class Car {

    private String carName;
    private Integer price;
    private String color;
    ......

    }

    <!--给 car 注入参数-->
    <bean id="car01" class="cn.imooc.pojo.Car">
        <property name="carName" value="梅赛德斯"></property>
        <property name="price" value="1000"></property>
        <property name="color" value="blue"></property>
    </bean>

    <!--给 user 注入参数-->
    <bean id="user05" class="cn.imooc.pojo.User">
        <!--引用 car01-->
        <property name="car" ref="car01"></property>
        <!--改变car的价格-->
        <property name="car.price" value="1"></property>
    </bean>

    @Test
    public void test4(){
        User iocUser = ioc.getBean("user05", User.class);
        System.out.println(iocUser);
    }

    输出结果
    User{name='null', age=null, sex='null', car=Car{carName='梅赛德斯', price=1,     
    color='blue'}}

⑭ 通过继承实现 bean 配置信息的重用

    <!--给 car 注入参数-->
    <bean id="car01" class="cn.imooc.pojo.Car">
        <property name="carName" value="梅赛德斯"></property>
        <property name="price" value="1000"></property>
        <property name="color" value="blue"></property>
    </bean>
    <!--parent: 指定当前 bean 的配置信息继承于哪个-->
    <bean id="car02" class="cn.imooc.pojo.Car" parent="car01">
        <property name="carName" value="一汽大众"></property>
        <!--price color的值 继承 car01-->
    </bean>

⑮ 通过 abstrac 属性创建一个模板 bean

    <!--给 car 注入参数-->
    <!--abstract=true: 这个 bean 的配置是抽象的,只能被继承,不能实例化 -->
    <bean id="car01" class="cn.imooc.pojo.Car" abstract="true">
        <property name="carName" value="梅赛德斯"></property>
        <property name="price" value="1000"></property>
        <property name="color" value="blue"></property>
    </bean>

⑯ 对象创建顺序

    spring 默认按照bean配置的顺序创建bean,通过 depends-on 改变创建顺序

    <bean id="book1" class="cn.imooc.pojo.book.Book1" depends-on="book2,book3"></bean>
    <bean id="book2" class="cn.imooc.pojo.book.Book2"></bean>
    <bean id="book3" class="cn.imooc.pojo.book.Book3"></bean>

 

四、工厂方法创建对象

① 静态工厂方法

    工厂本身不用创建对象,通过静态方法调用,对象=工厂类 . 工厂方法名 

    public class CarStaticFactory {

    private static Car getCar(){
        System.out.println("正在生产汽车");
        Car car = new Car();
        car.setCarName("梅赛德斯");
        car.setPrice(100);
        car.setColor("blue");
        return car;
        }
    }

    <!--facroty-mothod 指定哪个方法是工厂方法-->
    <bean id="car01" class="cn.imooc.factory.CarStaticFactory" factory-method="getCar">
        <property name="carName" value="奔驰"></property>
    </bean>

② 实例工厂方法

    先配置实例工厂对象,后调用实例工厂对象的方法

    <!--配置实例工厂对象-->
    <bean id="carInstanceFactory" class="cn.imooc.factory.CarInstanceFactory"></bean>

    <!--factory-bean 指定具体的实例工厂对象-->
    <bean id="car02" class="cn.imooc.factory.CarInstanceFactory"
          factory-bean="carInstanceFactory" factory-method="getInstanceCar">
    </bean>

          不管是单例还是多例对象,ioc 容器启动的时候都不主动创建对象,获取的时候才创建对象,单例只创建一个对象,多例则是只要获取就创建一个新的对象

          

    /**
     * 1、编写一个FactoryBean的实现类
     * 2、注册到 spring 配置文件中
     */
    public class MyCarFactoryBean implements FactoryBean<Car> {

    /**
     * getObject: 工厂方法
     * 返回创建的对象
     * @return
     * @throws Exception
     */
    public Car getObject() throws Exception {
        System.out.println("myfactory 为你创建对象");
        Car car = new Car();
        car.setCarName("奔驰");
        car.setPrice(1000);
        car.setColor("blue");
        return car;
    }

    /**
     * 返回创建的对象的类型
     * spring会自动调用这个方法来确认创建的对象是什么类型
     * @return
     */
    public Class<?> getObjectType() {
        return Car.class;
    }

    /**
     * 选择是否单例模式
     * @return
     */
    public boolean isSingleton() {
        return true;
        }
    }

    <!--FactoryBean是spring规定的一个接口
        它的实现类,spring都认为是一个工厂-->
    <bean id="myCarFactoryBean" class="cn.imooc.factory.MyCarFactoryBean"></bean>

  五、对象的作用域和生命周期

            当使用构造方法和工厂方法创建对象

            1、单例对象:容器启动的时候对象就被创建,对象会一直存在,容器销毁的时候,对象被回收

            2、多例对象:容器启动的时候不主动床架对象,只有当获取对象的时候才创建对象,每次获取的时候都会创建一个新的                    实例对象,需要手动回收对象      

            

    public class Car {

    private String carName;
    private Integer price;
    private String color;

    public Car() {
        System.out.println("创建car对象");
    }

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

    public void init(){
        System.out.println("对象创建");
        }
    }

    <!--设置销毁、初始化方法-->
    <bean id="car06" class="cn.imooc.pojo.Car"
    destroy-method="destroy" init-method="init" >
    </bean>

    @Test
    public void test1(){
        ConfigurableApplicationContext ioc = new 
    ClassPathXmlApplicationContext("ioc1.xml");
        Object car06 = ioc.getBean("car06");
        ioc.close();
        System.out.println(car06);
    }
    
    输出结果:
    创建car对象
    对象创建
    对象销毁
    Car{carName='null', price=null, color='null'}

六、Bean的后置处理器

          

public class InitCar implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化对象初始化之前");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws             BeansException {
        System.out.println("在对象初始化之后");
        return bean;
    }
}
    
    public class Car {

    private String carName;
    private Integer price;
    private String color;

    public Car() {
        System.out.println("创建car对象");
    }

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

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

     <!--设置销毁、初始化方法-->
    <bean id="car06" class="cn.imooc.pojo.Car"
    destroy-method="destroy" init-method="init" >
    </bean>

    <!--后置处理器实现类-->
    <bean class="cn.imooc.beanPostProcessor.InitCar"></bean>
    
    输出结果:
    创建car对象
    在初始化对象初始化之前
    对象初始化
    在对象初始化之后
    对象销毁
    Car{carName='null', price=null, color='null'}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值