Spring(一)
Spring的概述
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。
简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
Spring的特点
-
方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 -
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。 -
声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 -
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。 -
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。 -
降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。 -
Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
spring项目的搭建
下载spring开发包
官网:http://spring.io/
下 载 地 址 :http://repo.springsource.org/libs-release-local/org/springframework/spring
解压:(Spring 目录结构)
- docs :API 和开发规范.
- libs:jar 包和源码
- schema:约束
导入核心包
导入核心包和日志包
image.png
image.png
引入约束
先按下图导入约束
在src
下新建一个applicationContext.xml
文件
编写一个<beans></beans>
切换到Design模式,然后按下图导入
就可以看到有提示了
image.png
快速入门
- 编写一个
UserDao
的接口
package com.cuzz;
public interface UserDao {
public void sayHello();
}
- 编写一个
UserDao
接口的实现类
package com.cuzz;
public class UserDaoImpl implements UserDao {
@Override
public void sayHello() {
System.out.println("Hello Spring...");
}
}
- 在
applicationContext.xml
配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- spring快速入门 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符.
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
-->
<bean name="userDao" class="com.cuzz.UserDaoImpl"></bean>
</beans>
- 测试
package com.cuzz;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
@Test
public void fun1() {
// 创建spring工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂解析xml获取Bean的实例
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.sayHello(); // 输出 Hello Spring...
}
}
出现以下错误 WARN No appenders could be found for logger]
解决办法:在src下面新建file名为log4j.properties
内容如下:
# Configure logging for testing: optionally with log file
log4j.rootLogger=WARN, stdout
# log4j.rootLogger=WARN, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
IOC和DI
- IOC(Inversion of Control): 控制反转,将对象的创建权交给了Spring
- DI(Dependency Injection):依赖注入,需要有IOC的环境,Spring在创建这个类的过程中,Spring将类的依赖的属性设置进去
Spring 中的工厂
ApplicationContext
ApplicationContext
接口有两个实现类
- ClassPathXmlApplicationContext :加载类路径下 Spring 的配置文件
- FileSystemXmlApplicationContext :加载本地磁盘下 Spring 的配置文件
BeanFactory(已经过时)和 ApplicationContext
- BeanFactory :是在
getBean
的时候才会生成类的实例. - ApplicationContext :在加载
applicationContext.xml
(容器启动)时候就会创建
scope属性:Bean的作用范围
- singleton :默认值,单例的
- prototype :多例的
- request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
- session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
- globalSession :WEB 项目中,应用在 Porlet 环境,如果没有 Porlet 环境那么 globalSession 相当于 session
Bean 的生命周期的配置
通过配置<bean>
标签上的 init-method
作为 Bean
的初始化的时候执行的方法,配置 destroy-method
作为 Bean
的销毁的时候执行的方法,销毁方法想要执行,需要是单例创建的 Bean
而且在工厂关闭的时候,Bean
才会被销毁
导入其他配置
<import resource="com.cuzz.applicationContext2.xml"/>
Spring的Bean的属性注入
新建一个Car
类
package com.cuzz.pojo;
public class Car {
private String name;
private Integer price;
public Car() {
super();
}
public Car(String name, Integer price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Car [name=" + name + ", price=" + price + "]";
}
}
新建一个User
类
package com.cuzz.pojo;
public class User {
private String name;
private Integer age;
private Car car;
public User() {
super();
}
public User(String name, Integer age, Car car) {
super();
this.name = name;
this.age = age;
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
- 三种注入方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
">
<!-- spring快速入门 -->
<!-- Bean元素:使用该素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符.
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
-->
<bean name="userDao" class="com.cuzz.UserDaoImpl"></bean>
<!-- 构造方法的方式 -->
<!-- name属性:构造函数的参数名 -->
<!-- index属性:构造函数的参数索引 -->
<!-- type属性:构造函数的参数类型 -->
<bean name="user" class="com.cuzz.pojo.User">
<constructor-arg name="name" value="cuzz" index="0"/>
<constructor-arg name="age" value="18" index="1"/>
<constructor-arg name="car" ref="car" index="2"/>
</bean>
<!-- set方法的方式 -->
<bean name="car" class="com.cuzz.pojo.Car">
<property name="name" value="路虎" />
<property name="price" value="1000000" />
</bean>
<bean name="user2" class="com.cuzz.pojo.User">
<property name="name" value="faker"/>
<property name="age" value="20"/>
<!-- 注入对象类型的属性 -->
<!-- ref 属性:引用另一个 bean 的 id 或 name -->
<property name="car" ref="car"/>
</bean>
</beans>
- p名称空间的注入
<!-- p名称空间注入, 走set方法
1.导入P名称空间 xmlns:p="http://www.springframework.org/schema/p"
2.使用p:属性完成注入
|-值类型: p:属性名="值"
|-对象类型: p:属性名-ref="bean名称"
-->
<bean name="user3" class="com.cuzz.pojo.User" p:name="uzi" p:age="20" p:car-ref="car" >
</bean>
- spel注入: spring Expression Language sping表达式语言
<bean name="user4" class="cn.itcast.bean.User" >
<property name="name" value="#{user.name}" ></property>
<property name="age" value="#{user3.age}" ></property>
<property name="car" ref="car" ></property>
</bean>
- 复杂类型注入
<bean name="cb" class="com.cuzz.CollectionBean" >
<!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可
<property name="arr" value="tom" ></property>
-->
<!-- array注入,多个元素注入 -->
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user4" />
</array>
</property>
<!-- 如果List中只准备注入一个值(对象),直接使用value|ref即可
<property name="list" value="jack" ></property>-->
<property name="list" >
<list>
<value>jack</value>
<value>rose</value>
<ref bean="user3" />
</list>
</property>
<!-- map类型注入 -->
<property name="map" >
<map>
<entry key="url" value="jdbc:mysql:///crm" ></entry>
<entry key="user" value-ref="user4" ></entry>
<entry key-ref="user3" value-ref="user2" ></entry>
</map>
</property>
<!-- prperties 类型注入 -->
<property name="prop" >
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>