Spring框架学习笔记1:初步搭建和初步使用
Spring引言
介绍:Spring于2002年问世,它是一个开源的 轻量级的J2EE的项目管理框架,包含了多种设计模式(例如:工厂模式,策略模式,代理模式,单例模式等等)。
优势:Spring框架的优势在于,它提供了一个简单的、统一的、高效的方式来构造整个应用,并且将各个单层框架组合在一起。例如之前的struts框架(替换了原有的servlet)一般用在逻辑层,mybatis框架(替换了原有的jdbc)一般用在业务层,他们的使用是分离的,开发人员需要熟悉两套框架,并且给程序的维护带来一定影响。而spring框架可以把他们揉合起来使用,构建一个连贯的体系。(不是将其替换,而是将其整合管理)
Spring框架具体在项目中的核心使用:可以理解成项目管理框架,就是用来对现有项目中的组件进行管理(创建,使用,销毁)。【例如:在一个java项目中,我们常用到的组件有Controller,Service,DAO,Entity等。在Controller中有一个UserController,我们会在UserController中调用UserServiceImpl,调用UserDAO等。通常我们都会使用new关键字进行调用,而在Spring框架中,这个过程交由Spring来进行管理。注意:Entity组件一般不会交给Spring进行管理,还是通过new的方式进行使用。】
Spring第一步
1.引入spring框架相关依赖
spring-core:核心依赖
2.引入spring框架配置文件
配置文件:名字随便,位置随便(需要在本项目中的resources目录中)
applicationContext.xml spring.xml
3.通过spring管理组件
<!--通过spring管理组件
bean:用来管理组件对象的创建
class: 用来指定管理组件对象的全限定名
id:用来指定spring框架创建的当前组件对象在spring(容器|对象工厂)中唯一标识
-->
<bean class="com.wuhaotian.init.UserDAOImpl" id="userDaoImpl"></bean>
4.启动spring
//启动工厂
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
//获取工厂中创建好的对象,参数:获取工厂中指定对应的唯一标识
UserDAO userDao = (UserDAO)context.getBean(“userDaoImpl”);
userDao.save(“xiaoli”);
一些小记
1、ApplicationContext就是IOC容器的接口,可以通过此对象获取容器中创建的对象
2、对象在Spring容器创建完成的时候就已经创建完成,不是需要用的时候才创建.此种情况满足的是单例模式。
3、对象在IOC容器中存储的时候默认 都是单例的(单例的意思是,不论我们从工厂中拿多少次bean对象,我们拿到的都是同一个,相比使用new来创建对象,每次都要重新申请内存空间的方式,就会节省很多内存),如果需要多例需要修改属性 scope=“prototype”
4、创建对象给属性赋值的时候是通过set方法实现的,不能省略
public void setid(int id){
this.id = id;
}
5、对象的属性是由setter/getter方法决定的,而不是定义的成员属性
spring对象的获取及属性赋值方式
1、通过bean的id获取IOC容器中的对象
2、通过bean的类型获取对象
注意:通过bean的类型在查找对象的时候,在配置文件中不能存在两个 类型一致的bean对象,如果有的话,可以通过如下方法
3、通过构造器给bean对象赋值
4、通过命名空间为bean赋值,简化配置文件中属性声明的写法
5、bean对象在创建的时候是按照bean在配置文件的顺序决定的,也可以使用depend-on标签来决定顺序
6、控制通过scope属性可以指定当前bean的作用域
singleton:单例模式,从IOC容器中获取的都是同一个对象,默认的作用域
prototype:多例模式,从IOC容器中获取的对象每次都是新创建
注意:
如果是singleton的话,每次在创建IOC容器完成之前,此对象已经创建完成
如果是prototype的话,每次在需要用到此对象的时候,才会被创建
7、利用工厂模式创建bean对象
<!--利用工厂方法创建bean-->
<!--静态工厂-->
<bean id="person6" class="com.wuhaotian.factory.PersonStaticFactory" factory-method="getInstance">
<constructor-arg value="Libai"></constructor-arg>
</bean>
<!--实例工厂:先创建工厂实例,然后调用工厂方法实例
factory-bean:表示具体工厂类的实例
factory-method:表示具体工厂实例的方法
-->
<bean id="instanceFactory" class="com.wuhaotian.factory.PersonInstanceFactory"></bean>
<bean id="person7" class="com.wuhaotian.bean.Person" factory-bean="instanceFactory" factory-method="getInstance">
<constructor-arg value="Dufu"></constructor-arg>
</bean>
8、继承factorybean来创建对象
会在使用的时候才创建对象,不管对象是不是单例模式
FactoryBean是Spring规定的一个接口,当前接口的实现类,Spring都会将其作为一个工厂,但是在ioc容器启动的时候不会创建实例,只有在使用的时候才会创建对象
9、 spring中包含一个BeanPostProcessor的接口,可以在bean的初始化方法的前后调用该方法,如果配置了初始化方法的前置和后置处理器,无论是否包含初始化方法,都会进行调用。
10、 当一个对象中需要引用另外一个对象的时候,在之前的配置中我们都是通过property标签来进行手动配置的,其实在spring中还提供了一个非常强大的功能就是自动装配autowire,可以按照我们指定的规则进行配置,配置的方式有以下几种:
default/no:不自动装配.
byName:按照名字进行装配,以属性名作为id去容器中查找组件,进行赋值,如果找不到则装配null.
byType:按照类型进行装配,以属性的类型作为查找依据去容器中找到这个组件,如果有多个类型相同的bean对象,那么会报异常,如果找不到则装配null.
constructor:按照构造器进行装配,先按照有参构造器参数的类型进行装配,没有就直接装配null;如果按照类型找到了多个,那么就使用参数名作为id继续匹配,找到就装配,找不到就装配null.
11、SPEL SpEL:Spring Expression Language,spring的表达式语言,支持运行时查询操作对象
使用#{…}作为语法规则,所有的大括号中的字符都认为是SpEL.
ioc.xml
<bean id="person4" class="com.mashibing.bean.Person">
<!--支持任何运算符-->
<property name="age" value="#{12*2}"></property>
<!--可以引用其他bean的某个属性值-->
<property name="name" value="#{address.province}"></property>
<!--引用其他bean-->
<property name="address" value="#{address}"></property>
<!--调用静态方法-->
<property name="hobbies" value="#{T(java.util.UUID).randomUUID().toString().substring(0,4)}"></property>
<!--调用非静态方法-->
<property name="gender" value="#{address.getCity()}"></property>
</bean>
ioc.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--根据属性值设置的时候,name的名称取决于set方法后面的参数首字符小写的名称-->
<bean id="person" class="com.wuhaotian.bean.Person">
<property name="id" value="1"></property>
<property name="name" value="zhangsan"></property>
<property name="age" value="20"></property>
<property name="gender" value="male"></property>
</bean>
<!--使用构造器方法赋值的时候,name的名称取决于有参构造方法的形参的名称-->
<!--
name:表示参数列表的名称
value:表示实际的具体的值
type:表示值的类型(不支持自动转换)
index:表示值得下标,从0开始
-->
<bean id="person2" class="com.wuhaotian.bean.Person">
<constructor-arg name="id" value="2"></constructor-arg>
<constructor-arg name="name" value="lisi"></constructor-arg>
<constructor-arg name="gender" value="female"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
</bean>
<!--当通过构造器方法赋值的时候,可以省略namg属性不写,但是要注意保证参数值和构造器的参数列表的顺序一致-->
<bean id="person3" class="com.wuhaotian.bean.Person">
<constructor-arg value="22"></constructor-arg>
<constructor-arg value="lisi"></constructor-arg>
<constructor-arg value="2"></constructor-arg>
<constructor-arg value="f"></constructor-arg>
</bean>
<!--当有多个相同参数的构造方法存在的时候,默认的情况下是覆盖的过程,后面的构造方法会覆盖前面的构造方法-->
<bean id="person4" class="com.wuhaotian.bean.Person">
<constructor-arg value="2"></constructor-arg>
<constructor-arg value="lisi"></constructor-arg>
<constructor-arg value="female"></constructor-arg>
</bean>
<!--一般都会使用name,value的方式-->
<bean id="person5" class="com.wuhaotian.bean.Person"
p:age="12"
p:gender="male"
p:id="2"
p:name="wangwu">
</bean>
<bean id="person6" class="com.wuhaotian.bean.Person">
<property name="id" value="1"></property>
<property name="age" value="22"></property>
<property name="gender" value="female"></property>
<property name="name" value="liya"></property>
<property name="hobbies">
<array>
<value>book</value>
<value>girl</value>
<value>movie</value>
</array>
</property>
<!--给引用类型赋值-->
<property name="add" ref="add"></property>
<!--给list赋值-->
<property name="list">
<list>
<!--使用内部bean,无法从IOC容器中直接通过id获取对象-->
<bean id="address2" class="com.wuhaotian.bean.Address">
<property name="country" value="China"></property>
<property name="porvinces" value="shanghai"></property>
</bean>
<ref bean="add"></ref>
</list>
</property>
<!--给set赋值-->
<property name="set">
<set>
<value>zhangsan</value>
<value>zhangsan</value>
<value>liya</value>
</set>
</property>
<!--给map赋值-->
<property name="map">
<map>
<entry key="1" value="liya"></entry>
<entry key="2" value="haotian"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="a">1</prop>
<prop key="b">2</prop>
<prop key="c">3</prop>
</props>
</property>
</bean>
<bean id="add" class="com.wuhaotian.bean.Address">
<property name="country" value="china"></property>
<property name="porvinces" value="Hebei"></property>
</bean>
</beans>