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视频。

  • 相关阅读:
    利用栈实现字符串中三种括号的匹配问题c++语言实现
    十进制数转N进制c++实现
    字符单链表识别数字,字母,其它字符,并分为三个循环链表的算法c++实现
    c++两数组合并算法
    c++顺序表(数组)查找最大最小值
    SSO单点登录、跨域重定向、跨域设置Cookie、京东单点登录实例分析
    php实现单点登录,顶级域名与子域名间共享Cookie实现单点登录原理
    php实现单点登录实例
    php实现SSO单点登录实例
    玩转音频、视频的利器:FFmpeg
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/12729338.html
Copyright © 2011-2022 走看看