zoukankan      html  css  js  c++  java
  • Spring(一)——IOC

    重新正经学框架,从Spring开始!

    1.概念

    框架框架,就是项目的架子,也就是半成品,需要完善,而不能作为完整项目。

    2.核心

    IOC:控制反转。大白话讲就是原本我们用对象是new出来玩,现在去XML配置文件里配置,直接用。

    AOP:面向切面方程。大白话讲就是,切进去,原来的代码上加东西不影响原来的。

    3.搭建环境

    (1)建一个普通文件夹(Folder)lib加入jar包

    • spring-beans
    • spring-context
    • spring-core
    • spring-expression
    • commons-loging(日志包)

    按住shitf点第一个和最后一个包保证全选,右键build path添加路径。

    (2)建一个源文件夹(Source Folder)conf放配置文件,默认名applicationContext,每一个标签对<bean></bean>代表一个对象,属性中要设置是哪个类:包+类名,用id属性作为唯一标识,可以给对象赋值。

    4.使用

    (1)写一个类,例如类名叫Person,属性有名字name、序号id、年龄age,然后在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="person1" class="com.atguigu.spring.mod.Person">
            <property name="age" value="22"></property>
            <property name="name" value="守林鸟"></property>
        </bean>
        <bean id="person2" class="com.atguigu.spring.mod.Person"></bean>
        <bean id="person3" class="com.atguigu.spring.mod.Person"></bean>
    </beans>

    第1行理解成“我是xml文件”,照抄就行。

    接下来4行是命名空间,理解成“我要用Spring技术”,照抄就行。

    接下来3行的3对<bean>标签表示3个对象,可以设置id和name,id是唯一标识不能重复,如果没有设置name和id,默认class值当作id使用。

    <property>标签表示为对象的属性赋值,赋值,这就是所谓的DI,依赖注入,是IOC具体的实现方式。<property>中的name对应的是set方法而不是属性名。

    注入方法还可以用构造器,写构造方法,构造注入

    <constructor-arg value="" index="1/2/3" type="java.lang.Double"></constructor-arg>;

    很麻烦,index表示构造方法第几个参数,type表示通过类型区分重载构造器,可不加,容易出错。

    在main函数中这样使用XML文件中配置的对象。

        public static void main(String[] args) {
            //初始化容器
            ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
            //通过getBean()获取对象
            Person person1=(Person)ac.getBean("person1");
            System.out.println(person1);
        }

    第二种方法,用反射技术获取类对象,但是这个技术要保证对象唯一,一个类只能有一个<bean>标签,上面的配置文件不能用这个方法。

    Person person2=(Person)ac.getBean(Person.class);

    第三种方法,id+类对象

    Person person3=(Person)ac.getBean("person3",Person.class);

    5.p命名空间

    在xml文件的命名空间处加入p命名空间,设值注入写法会变得简单。

    <?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"
         
        xmlns:p="http://www.springframework.org/schema/p"
        >
        
        <bean id="person1" class="com.atguigu.spring.mod.Person">
            <property name="age" value="22"></property>
            <property name="name" value="守林鸟"></property>
        </bean>
        
        <bean id="person2" class="com.atguigu.spring.mod.Person" p:id="10086" p:name="灰太狼" p:age="19"></bean>
    </beans>

    6.字面量和ref

    在上面的设值注入都是value等于一个字符串,这就是字面量,基本类型的包装类型可以这么玩。

    但如果是一个有多个属性的引用类型就不可以这样玩,怎么办?用<bean>标签再写一个对象,用ref替换value,普通写法和p命名空间的写法如下

        <bean id="person1" class="com.atguigu.spring.mod.Person">
            <property name="age" value="22"></property>
            <property name="name" value="守林鸟"></property>
            <property name="teacher" ref="teacher"></property>
        </bean>
        
        <bean id="person2" class="com.atguigu.spring.mod.Person" 
        p:id="10086" p:name="灰太狼" p:age="19" p:teacher-ref="teacher"></bean>
        
        <bean id="teacher" class="com.atguigu.spring.mod.Teacher">
            <property name="lesson" value="大数据"></property>
            <property name="age" value="30"></property>
        </bean>

    7.联级查询

    对引用类型的属性赋值,用".",会对引用类型的对象造成影响,如果这个引用类型被多个对象引用,都会造成影响。

        <bean id="person1" class="com.atguigu.spring.mod.Person">
            <property name="age" value="22"></property>
            <property name="name" value="守林鸟"></property>
            <property name="teacher" ref="teacher"></property>
            <property name="teacher.lesson" value="大学语文"></property>
        </bean>

    8.内部bean

    定义在某个bean的内部,只能被当前bean使用。

        <bean id="person3" class="com.atguigu.spring.mod.Person">
            <property name="age" value="22"></property>
            <property name="name" value="霸王别鸡"></property>
            <property name="teacher">
                <bean id="tt" class="com.atguigu.spring.mod.Teacher">
                    <property name="lesson" value="高等数学"></property>
                    <property name="age" value="30"></property>
                </bean>
            </property>
        </bean>

    9.集合属性

    通过<list>,<set>,<map>,<array>等标签赋值。

    (1)例如Teacher类里加了几种属性,配置写法如下

        private List<String> list;
        private List<Student> students;
        private Map<String,Double> map;
        <bean id="teacher2" class="com.atguigu.spring.mod.Teacher">
            <property name="lesson" value="大学英语"></property>
            <property name="age" value="28"></property>
            <property name="list">
                <list>
                    <value>A</value>
                    <value>B</value>
                    <value>C</value>
                </list>
            </property>
            <property name="students">
                <list>
                    <ref bean="s1"/>
                    <ref bean="s2"/>
                    <bean id="s3" class="com.atguigu.spring.mod.Student">
                        <property name="name" value="小黑同学"></property>
                        <property name="score" value="88"></property>
                        <property name="age" value="14"></property>
                    </bean>
                </list>
            </property>
            <property name="map">
                <map>
                    <entry><!-- 键值对 -->
                        <key>
                            <value>儿子</value>
                        </key>
                        <value>2</value>
                    </entry>
                    <entry><!-- 键值对 -->
                        <key>
                            <value>女儿</value>
                        </key>
                        <value>3</value>
                    </entry>
                </map>
            </property>
        </bean>
        <bean id="s1" class="com.atguigu.spring.mod.Student">
            <property name="name" value="小明同学"></property>
            <property name="score" value="66"></property>
            <property name="age" value="12"></property>
        </bean>
        <bean id="s2" class="com.atguigu.spring.mod.Student">
            <property name="name" value="小红同学"></property>
            <property name="score" value="77"></property>
            <property name="age" value="13"></property>
        </bean>

    引用类型通过<ref bean=""/>引用或者直接开一个新的<bean>作为内部bean,注意点:只有<value>标签可以直接夹着字面量,像<key>等里面都还要再夹一个<value>赋值。

    也可以在XML直接定义一个集合,用<util:list><util:map>之类的标签,但是要加上命名空间。第7行和12-13行。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     
     5      
     6     xmlns:p="http://www.springframework.org/schema/p"
     7     xmlns:util="http://www.springframework.org/schema/util"
     8     
     9     xsi:schemaLocation="http://www.springframework.org/schema/beans 
    10      http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    11      
    12      http://www.springframework.org/schema/util
    13      http://www.springframework.org/schema/util/spring-util.xsd"
    14     
    15     >
        <bean id="teacher3" class="com.atguigu.spring.mod.Teacher">
            <property name="lesson" value="线性代数"></property>
            <property name="age" value="44"></property>
            <property name="students" ref="stulist"></property>
        </bean>
        <util:list id="stulist" >
            <ref bean="s1"/>
            <ref bean="s2"/>
        </util:list>

    写法如上,像其他集合的写法也差不多,要么新开对象,要么用ref引用。

    10.通过工厂来创造对象,用的是设计模式的工厂方法模式,没什么神秘的。

    11.bean的作用域

    属性scpoe=“作用域”加在<bean>标签里。

    注意点,单例是在初始化容器的时候就创建这个对象。而原型是每一次getBean()时创建一个。并且不写时默认单例

    12.bean的生命周期

    (1)通过构造器或者工厂方法创建bean实例

    (2)注入

    (3)调用初始化方法init

    (4)使用

    (5)容器关闭,调用bean的销毁方法

    其中,初始化方法和销毁一般不会调用,需要在<bean>标签的属性加上init-method="init" destroy-method="destroy",其中init和destroy是初始化方法和销毁方法的名字,可以重写。容器关闭用ac.close();初始化容器ac需要用实现类即ClassPathXmlApplicationContext,而不是ApplicationContext。

    13.bean的后置处理器

    在对象的初始化前后各执行一个方法,玩法:定义一个类AfterHandler实现BeanPostProcessor接口中的两个抽象方法,并且在配置文件中创建一下AfterHandler的bean,对配置文件中的所有都bean对象都起到处理作用。所以,两个方法里的内容不要涉及到 某一个对象没有的属性。

    14.引用外部属性/资源文件

    当bean的配置信息逐渐增多时,查找和修改一些bean的配置信息就变得愈加困难。这时可以将一部分信息提取到bean配置文件的外部,以properties格式的属性文件保存起来,同时在bean的配置文件中引用properties属性文件中的内容,从而实现一部分属性值在发生变化时仅修改properties属性文件即可。这种技术多用于连接数据库的基本信息的配置。properties文件是一种key-value的映射关系。写法如下:

    #key = value 
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring
    jdbc.username=root
    jdbc.password=shoulinniao
        <!-- 加载资源文件,db.properties,key-val的对应方法,相当于把内容写到资源文件中-->    
        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
            <property name="location" value="db.properties"></property>
        </bean>
        
          <!-- 另一种加载资源文件的方法 
          <context:property-placeholder location="db.properties" />
        -->
    
        
        <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driver}"></property>
            <property name="url" value="${jdbc.url}"></property>
            <property name="username" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>

    15.自动装配(即自动注入)

    • 手动装配:手写value和ref,上面的都是;
    • 自动装配:根据某种策略自动为非字面量属性赋值。

    需要用到的属性是<bean>标签里的autowire属性,autowire="byName || byType"。

    byName:需要配置的bean的属性名 等于 其他bean的id名。(id名唯一,所以也是唯一性)

    byType:需要配置的bean的属性类型 等于 其他bean的类型。(确保同类型只有一个bean,多个就不知道配哪个,和getBean唯一一个道理)

    建议:约束性太强了,别用。

    16.注解

    标识受Spring IOC容器管理的组件

    (1)大白话:哪个类标注了注解,就变成了组件。(什么是组件?组件就是Spring中的bean)用一个语句扫描 指定包下的类,对于加上注解的类进行加载。这些类的id名默认是单个首字母变小写的类名。

    (2)条件:添加Spring-aop包,命名空间第7行,location在15-16行。

     1 <beans xmlns="http://www.springframework.org/schema/beans"
     2     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     
     4      
     5     xmlns:p="http://www.springframework.org/schema/p"
     6     xmlns:util="http://www.springframework.org/schema/util"
     7     xmlns:context="http://www.springframework.org/schema/context"
     8     
     9     xsi:schemaLocation="http://www.springframework.org/schema/beans 
    10      http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    11      
    12      http://www.springframework.org/schema/util
    13      http://www.springframework.org/schema/util/spring-util.xsd
    14      
    15      http://www.springframework.org/schema/context 
    16      http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    (3)过滤器

    如果一次性把整个包的都扫描,有些不需要用的也扫,就有点浪费时间,所以有过滤器这个功能。包含与排除(include和exclude),可以同时包含,同时排除,不能同时包含和排除。包的范围可以用逗号,表示多个包。

           <context:component-scan base-package="com.atguigu.ioc" use-default-filters="false">
           
               <!-- 自定义包含过滤时,要把默认的过滤器关闭,即use-default-filters="false" -->
               <!-- 根据注解类型,只扫描 包中注解是@Componet的类,可以改成别的 -->
               <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
               
               <!-- 自定义排除过滤时,不要把默认的过滤器关闭,即use-default-filters="true"或不写 -->
               <!-- 根据注解类型,只不扫描 包中注解是@Service的类,可以改成别的 -->
               <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
               
               
               <!-- 根据类的类型,只扫描 包中类型是**的,过滤器同上 -->
               <context:include-filter type="assignable" expression="com.atguigu.ioc.scope.Teacher"/>
               <!-- 根据类的类型,只不扫描 包中类型是**的,过滤器同上 -->
               <context:include-filter type="assignable" expression="com.atguigu.ioc.scope.Student"/>
           </context:component-scan>

    (4)注解和自动装配的混合运用

    对特定类型的属性用@Autowired注解,会根据类型去xml中找指定的bean装配。

    (5)注解中的属性

    value表示在xml里装配之后生成的对应的bean的id不再是默认的类首字母小写,而是自己设置的value值

    @Component(value="aaa") 或者 @Component("aaa")


    学习资源:B站尚硅谷Spring视频。

  • 相关阅读:
    WPF Caliburn 学习笔记(五)HelloCaliburn
    MSDN 教程短片 WPF 20(绑定3ObjectDataProvider)
    MSDN 教程短片 WPF 23(3D动画)
    比赛总结一
    HDU3686 Traffic Real Time Query System
    HDU3954 Level up
    EOJ382 Match Maker
    UESTC1565 Smart Typist
    HDU3578 Greedy Tino
    ZOJ1975 The Sierpinski Fractal
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/12729338.html
Copyright © 2011-2022 走看看