1. 安装spring插件
SPRING TOOL SUITE 是一个 Eclipse 插件,利用该插件可以更方便的在 Eclipse 平台上开发基于 Spring 的应用。
- Install New Software…
- Add…
- Location
- 选择Navigate to springsource-tool-suite-3.4.0.RELEASE-e4.3.1-updatesite.zip
- 取消勾选 Contact all updata…
- 点击“Acailable Software Sites” 蓝色字体 取消所有http的选项勾选
- 一直下一步
- 关于错误处理
jdk版本 spring 版本 eclipse版本 引起的
2. spring概述
2.1spring是个啥?
开源的轻量级的框架,一个IOC(DI)和AOP容器框架,关于框架的特性,spring俗称开发框架的粘合剂
- 轻量级:Spring是非侵入性的,基于Spring开发的应用中的对象可以不依赖Spring的API
- 依赖注入:(DI—dependency Injection、IOC —Inversion of Control)
- 面向切面编程:(AOP aspect oriented programming)
- 容器:Spring 是个容器,因为它包含并且管理应用对象的生命周期
- 框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中可以使用xml和java注解组合这些对象
- 一站式:在IOC和AOP的基础上可以整合各个企业应用的开源框架和第三方类库
spring提供了JavaEE各层的解决方案
web表现层(页面数据显示、页面跳转调度):SpringMVC Struts2
service业务层(业务处理和功能逻辑、事务控制):IoC、AOP、事务控制
dao持久层(数据存取和封装):jdbcTemplate,HibernateTemplate,ORM框架
2.2spring框架runtime
- test:spring提供的测试功能
提供对使用JUnit和TestNG来测试Spring组件的支持,它提供一致的ApplicationContexts并缓存这些上下文,它还能提供一些mock对象,使得你可以独立的测试代码 - AOP:实现aop功能需要的依赖
- AOP:提供了符合AOP 联盟规范的面向方面的编程实现,让你可以定义如方法拦截器和切入点,从逻辑上讲,可以减弱代码的功能耦合,清晰的被分离开。而且,利用源码级的元数据功能,还可以将各种行为信息合并到你的代码中
- Aspect:提供了对AspectJ的集成
- Instrumentation
- WEB:需要spring完成web相关功能时需要
- Web:提供了基础的web功能,例如文件上传,集成IoC容器,远程过程访问及对web Service支撑
- Servlet:提供了Web应用的MVC实现,Spring MVC框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的JSP标签,完全无缝与Spring其他技术协作
- Portlet模块,提供了在Portlet环境下的MVC实现
- Data Access/Integration(数据访问/集成部分):spring封装数据访问层相关内容
- JDBC:Spring对JDBC封装后的代码
- ORM:提供了常用的“对象/关系”映射APIs的集成层,封装了持久层框架的代码:如Hibernate MyBatis
- transactions:对应spring-tx.jar,声明式事务使用,只要是Spring管理的对象都能得到spring管理事务的好处
- OXM:提供一个支持Object和XMl进行映射的抽象层
- JMS模块:提供一套"消息生产者、消费者"模板用于更加简单的使用JMS,JMS用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
- Core Container:核心容器,Spring启动的基本条件
- Beans:Spring负责创建对象并管理对象
- Core:核心类 ,和Beans模块提供了Spring最基础的功能,提供了IoC和依赖注入的特性,这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
- Context:上下文参数,获取外部资源或管理注解
Context模块基于Core和Beans来构建,Context封装包继承了beans包的功能,还增加了其他的功能,核心接口是ApplicationContext - SqEl:expression.jar 表达式语言模块,提供了在运行期间查询和操作对象图的强大能力。 "
2.3 spring的优点
- 方便解耦,简化开发
Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理 - AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能 - 声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程 - 方便程序测试
对Junit4支持,可以通过注解方便的测试Spring程序 - 方便集成各种优秀的框架
不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz、webservice、activity等)的直接支持 - 降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
3. IoC&DI
IOC控制返转
IoC完成的事情 由程序员主动通过new实例化对象事情转交给Spring完成
IoC是一种思想,是控制反转的思想,解耦的思想
spring是该思想的一种实现,因此spring容器也通常称之为IoC容器
将对象创建权利交给Spring工厂进行管理
控制:控制类的对象
反转:转交给spring对象
底层实现:工厂模式+反射+配置文件
最大作用:解耦 ,解除了对象管理和程序员之间的耦合,程序员不需要管理对象
DI 依赖注入
在spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件(将另外一个Bean对象动态的注入到另外一个bean中)
IoC和DI是同一件事情,都是将对象控制权交给第三方(spring)管理,只是站在不同角度而已(IoC是目的,DI是手段)
简单的说,就是我们类里需要另一个类,只需要让Spring帮我们创建 ,这叫做控制反转,然后Spring帮我们将需要的对象设置到我们的类中,这叫做依赖注入。
4. 代码实现
4.1导包
四个核心包一个日志包
commous-logging-1.1.3.jar
spring-beans-4.2.4RELEASE.jar
spring-context-4.2.4RELEASE.jar
spring-core-4.2.4RELEASE.jar
spring-expression-4.2.4RELEASE.jar
4.2配置文件
beans.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.xsd">
<!-- id 表示获取到对象标识class 创建哪个类的对象-->
<bean id="people" class="com.yn.People"/>
</beans>
4.3People类
public class Person {
private String name;
private int age;
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4.4测试
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
//使用Java反射来实现 默认是单例模式来创建对象
Person p=(Person)ac.getBean("person");
Person p2 = ac.getBean("person",Person.class);
System.out.println(p);
System.out.println(p2);
}
5. 依赖注入的三种方式
-
属性注入
- 通过构造方法设置值.
- 设置注入(通过 set 方法)
- 如果属性是基本数据类型或 String 等简单
-
<bean id="people" class="com.yn.People"> <property name="name" value="tom" ></property> <property name="age" value="18"></property> </bean>
- 如果属性是 Set<?>
-
<property name="sets"> <set> <value>1</value> <value>2</value> <value>3</value> <value>4</value> </set> </property>
- 如果属性是 List<?>
-
<property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property>
- 如果属性是数组
-
<property name="strs" > <array> <value>1</value> <value>2</value> <value>3</value> </array> </property>
- 如果属性是 map
-
<property name="map"> <map> <entry key="a" value="b" > </entry> <entry key="c" value="d" > </entry> </map> </property>
- 如果属性 Properties 类型
-
<property name="demo"> <props> <prop key="key">value</prop> <prop key="key1">value1</prop> </props> </property>
- 配置工具类集合
-
<!-- 首先导入util命名空间 --> xmlns:util="http://www.springframework.org/schema/util" <util:list id="pets"> <ref bean="cat"/> <ref bean="dog"/> </util:list>
- 使用p命名空间
-
<!-- 首先导入p命名空间 --> xmlns:p="http://www.springframework.org/schema/p" <bean id="pet" class="cn.yn.Pet" p:petName="鹦鹉" p:petType="鸟"></bean> <bean id="test1" class="cn.yn.Person" p:name="张全蛋" p:age="10" p:pet-ref="pet"></bean> <!-- 使用p命名空间(spring 2.5版本引入的) 可以简化bean的配置 -->
- null值
-
<constructor-arg name="name"> <null/> </constructor-arg>
- 自动装配
-
autowire = "byName" || "byType" 不推荐使用。 <!-- 可以通过autowire属性设置bean的自动装配 。 byName 根据bean的名字和bean,setter风格的属性名进行自动装配,如有匹配则自动装配,没有不装配。 byType 根据bean的类型,和当前bean属性的类型进行自动装配。如果ioc容器有1个以上类型匹配的bean的时候,则会抛出异常。 constructor 当前bean中有多个构造器的时候 会很复杂不推荐使用该方式。 自动装配的弊端。 1.autowire属性是配置在bean级别的,如果只希望装配个别属性,则不够灵活。 2.要么根据类型 要么根据名字自动装配 不能两个一起使用。 在使用spring整合第三方框架的时候 会使用autowire 。。。 --> <bean id="xm" class="cn.yn.Person" p:name="小明" autowire="byType"> </bean> <bean id="pet1" class="cn.yn.Pet" p:petName="发福蝶"></bean> <bean id="pet2" class="cn.yn.Pet" p:petName="小脑斧"></bean>
-
构造器注入
- 无参构造创建:默认情况.
- 有参构造创建:需要明确配置
- 需要在类中提供有参构造方法
- 在 配置文件 中设置调用哪个构造方法创建对象
- index : 参数的索引,从 0 开始
- name: 参数名
- type:类型(区分开关键字和封装类 int 和 Integer)
- ref:引用其他对象
<![CDATA[]]>
-
工厂方法注入 很少使用,不推荐
6. Bean 的作用域
由spring创建的bean对象在什么情况下有效。
类别 | 说明 |
---|---|
singleton | 在spring IoC容器中仅存在一个Bean实例,bean以单例方式存在 |
prototype | 每次从容器中调用Bean时,都会返回一个实例,即每次调用getBean()时,相当于new一个对象 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP session共享一个Bean,不同的Session使用不同的Bean,仅适用于WebApplicationContext环境 |
globalSession | 一般用于Porlet应用环境,仅适用于WebApplicationContext环境 |
Porlet: 基于Java的web组件
项目开发中通常使用singleton和prototype
7.Bean的生命周期
通过spring工厂,可以控制bean的生命周期
- 通过构造器或工厂方法创建Bean实例
- 为Bean的属性设置值,和对其他Bean的引用
- 调用Bean的初始化方法
- Bean可以使用了
- 当容器关闭,调用Bean的销毁方法
在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
spring提供可一个Bean后置处理器,允许在调用初始化方法前后对Bean进行额外的处理
Bean后置处理器对IoC容器里所有的Bean实例逐一处理,作用:检测bean属性的正确性,或者根据特定的标准更改bean属性
8. 使用外部属性文件
在配置文件中配置bean时,有时候需要混入系统部署的数据信息。
例如:文件路径,数据源配置。
实际上需要将这些数据跟bean的配置分离。
spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器。
可以使用${var}的形式,从属性配置文件中读取属性,并使用这些属性。
spring,2.5之后。可以通过<context:property-placeholder location=“classpath:db.properties”
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root123"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///test"></property>
</bean>
9. spring的工厂
Spring提供了两种类型的IoC容器实现
- BeanFactory:IOC容器的基本实现
采用延时加载,第一次getBean时才会初始化Bean对象 - ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向Spring框架的开发者
几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory .无论使用何种方式, 配置文件时相同的.
ApplicationContext
ApplicationContext 应用上下文 ,用来加载spring框架的配置文件,来构建spring的工厂对象,也称为Spring容器的上下文对象,也称为spring的容器
主要实现类
- ClassPathXmlApplicationContext:从 类路径下加载配置文件
- FileSystemXmlApplicationContext: 从文件系统中加载配置文件
ApplicationContext在初始化上下文时就是实例化所有的单例的Bean
10.Bean 之间的关系
-
继承
抽象Bean:abstract=“true”,不能被IoC实例化,只能用来被继承配置
如果一个Bean的Class值没有被指定,那么这个Bean的abstract属性必须为true
使用Bean的parent属性来制定继承哪一个Bean
-
依赖
通过depends-on 设置前置依赖的bean,依赖的bean会在当前bean实例化之前创建好。
如果依赖多个bean 可以使用 , | 和 空格 来区分多个bean。
11. 配置Bean 的三种方法
- 反射
- 工厂实现
- 注解
11.1工厂实现Bean的配置
11.1.1静态工厂实现
public class StaticFactory {
private static Map<String, Person> persons=new HashMap<String,Person>();
static {
persons.put("tom", new Person("Tom"));
persons.put("jack", new Person("Jack"));
}
//静态工厂方法
public static Person InstanceFactory(String name){
return persons.get(name);
}
}
//配置文件
<!-- 静态工厂方法配置Bean -->
<bean id="tom" class="com.yn.spring01.StaticFactory" factory-method="InstanceFactory">
<constructor-arg value="tom"></constructor-arg>
</bean>
//测试
ApplicationContext ac=new ClassPathXmlApplicationContext("com/yn/spring01/beans.xml");
Person bean = (Person) ac.getBean("tom");
System.out.println(bean);
11.2 实例工厂实现
public class InstanceFactory {
Map<String ,Person> map=null;
public InstanceFactory(){
map=new HashMap<String ,Person>();
map.put("xixi", new Person("Xixixixi"));
map.put("haha", new Person("Hahahahah"));
}
public Person getPerson(String name){
return map.get(name);
}
}
//配置文件
<!-- 实例工厂配置Bean -->
<bean id="instance" class="com.yn.spring01.InstanceFactory"></bean>
<bean id="xixi" factory-bean="instance" factory-method="getPerson">
<constructor-arg value="xixi"></constructor-arg>
</bean>
//测试
Person bean2 = (Person) ac.getBean("xixi");
System.out.println(bean2);
11.1.3 FactoryBean
public class PersonFactoryBean implements FactoryBean<Person> {
private String name;
public void setName(String name) {
this.name = name;
}
public Person getObject() throws Exception {
// TODO Auto-generated method stub
return new Person(name);
}
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Person.class;
}
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
}
//配置文件
<!-- FactoryBean 配置bean实例-->
<bean id="p" class="com.yn.spring01.PersonFactoryBean">
<property name="name" value="FactoryBean"></property>
</bean>
//测试
Person bean3 = (Person) ac.getBean("p");
System.out.println(bean3);
11.2 注解方式配置Bean
在使用注解时在之前的五个包里,还要加一个AOP包
在使用注解时,要在配置文件中开启扫描包
<!--
base-package 属性指定一个需要扫名的基类包,Spring容器会扫描这个基类包里及其子包中所有的的类
当需要扫描多个包时,可以使用逗号隔开
如果需要扫描特定的类,而非基类包下的所有类,可使用resource-Pattern 属性过滤特定的类
-->
<context:component-scan base-package="com" />
对于扫描的组件,spring有默认的命名策略:使用类名 第一个字母小写 也可以使用value属性标识组件
组件包裹 4 个
@Conponent 基本注解,标识一个受Springf IoC 容器管理的组件
@Respository 标识持久层
@Service 标识业务层
@Controller 标识控制层
组件装配
注入包裹 3 个
@AuthWired 自动装配具有兼容类型的单个Bean属性
@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 Bean 的名称
@Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性建议使用 @Autowired 注解
@AuthWired:可以使用在属性,set方法和构造器的前面
@Qualifier:提供了Bean的名称,Spring允许对方法的入参标注@Qualifier指定注入Bean的名称
12. spEl表达式
spring表达式语言 即 spEL:是一个运行时查询和操作对象图的强大表达式语言
使用#{}作为定界符 为bean属性动态赋值提供了便利
<property name="test" value="#{5}"/>
<property name="test" value="#{3.14}"/>
<property name="test" value="#{1e4}"/>
<property name="test" value="#{'哈哈'}"/>
<property name='test' value='#{"嘿嘿"}'/>
<!--引用其他bean对象,等价于ref属性。-->
<property name="pet" value="#{pet1}"></property>
<!--引用其他bean对象的属性。 -->
<property name="pet" value="#{pet1.petName}"></property>
<!--拿到方法的返回值。 -->
<property name="name" value="pet1.toString()"></property>
<!--链式调用。-->
<property name="name" value="pet1.toString().toUpperCase()"></property>