透明哥学习Spring (1)

1.1、Spring概述

        spring框架的核心:

一:控制饭庄,反转资源控制方向,将自己创建资源转变为向环境索取资源,享受资源的注入。

二:AOP--面向切面编程,java的继承机制是纵向继承机制,这不利于程序的封装,而面向切面编程(AOP)是横向抽取机制的。

1.2、IOC

1.2.1、IOC容器

IOC思想:说白就是反转控制,将对象的控制权反转给IOC容器

DI:依赖注入,说白了就是赋初始值,组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器 的资源注入

1.2.2、IOC容器在Spring中的实现

IOC容器有两种实现方式:

①BeanFactory,是Spring内部使用的接口,面向Spring开发者。

②ApplicationContext,BeanFactory的子接口,是专门为开发者提供

内部类的继承关系

 注意:

ClassPathXmlApplicationContext是通过读取类路径下的 XML 格式的配置文件创建 IOC 容器 对象

FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容 器对象(一般不用,可移植性比较差)

1.2.3、基于XML方式管理Bean

实验一:简单入门:

创建Spring配置文件:

 配置Bean标签:

 其中id是唯一表示,class设置bean所对应类型的全类名。

下面是测试文件

 注意:resource和java最终会被加载到同一个路径下,所以写类名时可以不用写全类名。

通过Bean标签的id属性来获取对象,最后调用sayHello()方法,获取的对象时Object类型,要进行向下转型。

注意点:IOC底层是通过反射来进行的,因为反射的时候就是调用空参构造器,那么对于类HelloWorld而言一定要有空参构造器,否则会报错误。

实验二:获取Bean对象的三种方式

方式一(根据Bean的id来获取对象):由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象。

方式二:根据类型获取IOC容器,但是这是有条件的:当根据类型获取bean时,要求IOC容器中指定类型的bean有且只能有一个,这也是实际开发中最最常用的方式,因为实际开发中只会出现一个Bean标签。

 方式三:根据id和类型

注意:根据id和类型获取一级根据id获取,不用向下转型

注意:一个java类对应一个Bean标签,对应一个组件。

扩展:

如果组件类实现了接口,根据接口类型可以获取得到Bean

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型不可以获取 bean

实验三:依赖注入之setter注入:

所谓依赖注入,含义就是为属性对象赋值的过程,主要分为setter注入和构造器注入。

property标签:为属性赋值,调用的是setXXX方法,为属性赋值,name指定属性名,value属性用于指定属性名。

实验四:依赖注入之构造器注入:

构造器注入的基本条件是要求java类中有对应的构造器,之后配置Bean就可以了

上图中value属性用于指定给哪个变量进行赋值,name属性专门指定赋值的属性是age属性,这是为了防止java类中有两个相同类型的构造器(最后一个参数都是数值类型的)。 

实验五:特殊值处理

①字面量的处理,这个在上面已经讨论过了

②null值的处理

注意:不可以直接在value属性中设置,null属性,这样会解析成为"null"字符串,如下面所示

<constructor-arg >
    <null/>
</constructor-arg>

②xml实体,所谓的xml实体,由于配置文件是xml文件,因此不可以对<>等关键词进行赋值,

方法一:要用实体来进行替代,如下面所示:

 就是<李四>

方法二:用CD Data区,CD Data区中的数据会被原样解析,如下所示

CD Date区在idea中的快捷键是CD(一定要大写)

 实验六:为类类型的属性进行赋值

注意:对一对应对象,对多对应集合(再次强调),下面的代码中,在Student对象中有一个Clazz类的类型对象。

三种方式:

方式一:引用外部已经声明的Bean

<bean id="Clazz" class="com.atguigu.spring.pojo.Clazz">
        <property name="cname" value="牛逼的人"></property>
        <property name="cid" value="1111"></property>
        <property name="students" ref="studentList">
        </property>
</bean>  
  <bean id="studentFive" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="name" value="赵六"></property>
        <property name="gender" value="男"></property>
        <property name="age" value="26"></property>
        <property name="clazz" ref="Clazz"></property>
    </bean>

方式二:内部bean进行处理

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="name" value="赵六"></property>
        <property name="gender" value="男"></property>
        <property name="age" value="26"></property>
        <property name="clazz">
            <bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
                        <property name="cid" value="1112"></property>
                        <property name="cname" value="远大前程"></property>
            </bean>
        </property>

</bean>

方式三:通过级联的方式进行

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="name" value="赵六"></property>
        <property name="gender" value="男"></property>
        <property name="age" value="26"></property>
        <property name="clazz" ref="Clazz"></property>
<!--        使用级联的方式,但是需要提前为class属性进行赋值或者进行实例化,用的并不是很多-->
        <property name="clazz.cid" value="1112"></property>
        <property name="clazz.cname" value="远大前程"></property>
        </property>

</bean>

注意:使用级联的方式是用的最少的,因为不一定知道具体要赋值的类的对象。

实验七:为数组类型属性赋值

为Student类型中添加属性:

 对Bean进行配置

    <bean id="studentFive" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="name" value="赵六"></property>
        <property name="gender" value="男"></property>
        <property name="age" value="26"></property>
            <bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
                        <property name="cid" value="1112"></property>
                        <property name="cname" value="远大前程"></property>
            </bean>
        </property>
        <property name="hobby">
            <array>
                <value>唱</value>
                <value>跳</value>
                <value>rap和篮球</value>
            </array>
        </property>
    </bean>

通过Array标签可以对数组类型的属性赋予初始值

实验八:为集合类型的属性赋值

在Class类中添加属性:

 配置Bean

方式一:同数组类型一样

 <bean id="Clazz" class="com.atguigu.spring.pojo.Clazz">
        <property name="cname" value="牛逼的人"></property>
        <property name="cid" value="1111"></property>
        <property name="students">
<!--            这是进行赋值的方式一-->
            <list>
                <ref bean="studentOne"></ref>
                <ref bean="studentTwo"></ref>
                <ref bean="studentThree"></ref>
            </list>
        </property>
    </bean>

方式二:应用utils约束

 <bean id="Clazz" class="com.atguigu.spring.pojo.Clazz">
        <property name="cname" value="牛逼的人"></property>
        <property name="cid" value="1111"></property>
        <property name="students" ref="studentList">
        </property>
    </bean>
<!--  配置一个集合类型的bean,然后使用utils类型的约束  -->
<utils:list id="studentList">
        <ref bean="studentOne"></ref>
        <ref bean="studentTwo"></ref>
        <ref bean="studentThree"></ref>
</utils:list>

实验九:为Map类型的属性赋值

方式一:通过Map标签进行处理,运用子标签entry对key和value两个属性进行赋值 

在Student中添加属性:

 在xml中配置属性:

方式二:运用utils约束

实验十:使用命名空间

 这也是一个约束

实验十一:引入外部属性文件

首先引入外部属性文件

<context:property-placeholder location="jdbc.properties">
</context:property-placeholder>
引入外部属性文件以后,就可以根据${}的方式访问属性名字
<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>

实验十二:Bean的作用域

spring可以通过配置bean标签的scope属性来指定bean的作用域,具体如下面所示:

singleton表示是单例模式,propotype表示不是单例模式

实验十三:Bean的生命周期

bean对象创建(调用无参构造器)

给bean对象设置属性 bean对象初始化之前操作(由bean的后置处理器负责)

bean对象初始化(需在配置bean时指定初始化方法)

bean对象初始化之后操作(由bean的后置处理器负责)

bean对象就绪可以使用 bean对象销毁(需在配置bean时指定销毁方法)

IOC容器关闭

实验十四:FactoryBean

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个 FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是 getObject()方法的返回值

具体如下所示:

 配置的Bean

 通过上面getObject方法得到的返回值,返回我要的bean对象

实验十五:基于XML自动装配Bean

根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或接口类 型属性赋值。

自动装配主要有两种方式:byType(主要使用方式,根据类型自动装配Bean对象,要求Bean标签中有且只有一个类型对应的Bean)和byName(根据名称自动寻找Bean对象,这时候默认寻找的id是所要赋值的属性名,通过属性名进行配置)

<bean id="userControl" class="com.atguigu.spring.control.UserControl" autowire="byType">
<!--            <property name="userService" ref="userService"></property>-->
    </bean>
    <bean id="userService" class="com.atguigu.spring.service.impl.UserServiceImpl" autowire="byType">
<!--            <property name="userDao" ref="userDao"></property>-->
    </bean>
    <bean id="userDao" class="com.atguigu.spring.dao.impl.UserDaoImpl">
    </bean>

1.2.4 基于注解管理Bean

实验一:标记和扫描

首先,注解本身是一个标记,具体执行要交给框架底层进行实行,Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注 解进行后续操作。

标识足交所使用的注解:

@Component:将类标识为普通组件

@Controller:将类标识为控制层组件

@Service:将类标 识为业务层组件

@Repository:将类标识为持久层组件

这四个注解本质上是一样的,只不过未了程序员容易理解,所以用了四个注解

扫描组件(初始的扫描方式):

 <context:component-scan base-package="com.atguigu.spring">     
 </context:component-scan>

这里是根据包进行扫描,表示扫描com.atguigu,spring 下面的所有类

扫描组件的两个标签(exclude和include标签):

 <context:component-scan base-package="com.atguigu.spring">
        <!--        这是根据注解进行排除-->
               <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--        这是根据类的类型进行排除-->
     <context:exclude-filter type="assignable" expression="com.atguigu.spring.control.UserControl"/>
    </context:component-scan>

这个扫描标签有两个属性

include标签表示只扫描指定的组件,但是必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类。

重点:

@Autowired注解的原理
* a>默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
* b>若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果
* 即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
* c>若byType和byName的方式都无妨实现自动装配,即IOC容器中有多个类型匹配的bean
* 且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NoUniqueBeanDefinitionException
* d>此时可以在要赋值的属性上,添加一个注解@Qualifier
* 通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值
*
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值