Spring概述
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring。
Spring是全面的和模块化的。Spring有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。因此从你的学习中,你可得到最大的价值。例如,你可能选择仅仅使用Spring来简单化JDBC的使用,或用来管理所有的业务对象。
Spring核心内容
IOC【控制反转】
IOC【Inverse Of Control】控制反转:所谓控制反转就是把对象(bean)对象和维护对象(bean)之间的关系的权利转移到Sqring容器中去了(ApplicationContext.xml)而程序本身不在维护了
DI【Dependency Injection】依赖注入:实际上DI和IOC是同一个概念,因为在ApplicationContext.xml配置文件中bean和bean之间通过ref来维护的时候是相互依赖的,所以又叫做依赖注入。也就是控制反转。
总结:对象的关系依赖于容器注入,由容器管理,对象自己不需要管理
AOP【面向切面】
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
可以用于:日志记录,性能统计,安全控制,事务处理,异常处理等等
Spring使用AOP的功能完成各种共用的模板功能,使得我们的业务代码与其它代码分开
IOC原理
推导过程:
1.传统采用new方式实例化对象,此种方式耦合度较高
2.故可以使用泛型来降低耦合度,但泛型的形式仍然存在耦合度
3.那么采用工厂模式彻底解决使用实例化对象时产生的耦合度,但工厂又产生了耦合度
4.可以采用XML配置+反射创建对象+工厂模式的形式来彻底解决工厂产生的耦合度
底层原理:xml+dom4j+工厂设计模式+反射
模块化
Spring3.0 之后,就根据模块化的形式进行开发:
Spring所有的其它功能都是基于容器。
模块化的目的是为了降低程序的整体复杂度,使程序设计、调试和维护等简单化。各个模块可独立工作,即便单模块出现故障,也不影响整个系统工作。模块化具有三个特性:相互独立,可替换,通用。
导入jar包
先导入核心包(core)与beans包【最小配置包】
导包的时候注意,现在使用Spring,要完成最小导包,即:需要什么jar包,我们就导入哪一个jar包,这个对认识框架的包是非常有帮助的。不然以后由于出现问题自己都不知道应该怎么解决。
创建配置文件
Spring的配置文件名称可以随便定义,创建在src根目录下
可以直接拷贝如下配置:
<?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">
也可以使用英文文档中的配置:
创建好的配置文件
配置文件报错问题
BeanFactory测试获取对象
@Test
public void testGetBean2() throws Exception {
/**
* 需求:获取对象
* 1.获取配置文件
* 2.获取工厂对象
* 3.获取对象
*/
ClassPathResource resource = new ClassPathResource("application.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
User u = (User) factory.getBean("user");
System.out.println(u);
}
Spring获取对象
Bean配置信息
基本Bean配置
id属性:标识配置的bean,唯一且不能有特殊符号【Spring3.2前】
name属性:和id功能相同,但可以使用特殊符号,Spring3.2后不区分id
name class属性:配置bean的完全限定名
配置一个基本的Bean对象:
<bean id="user" class="cn.itdemo.test.User"></bean>
工厂方式获取对象
factory-bean属性:用于工厂模式创建对象的形式,使用定义的工厂类的id
factory-method属性:工厂类中用于创建对象的方法
静态工厂方式:【静态方法】
public class BeanFactory {
public static User getUser(){
return new User();
}
}
配置信息
<bean id="user2" class="cn.itdemo.test.BeanFactory" factory-method="getUser"></bean>
实例工厂方式:【实例方法】
public class BeanFactory2 {
public User getUser(){
return new User();
}
}
配置信息
<bean id="factory" class="cn.itdemo.test.BeanFactory2"></bean>
<bean id="user3" factory-bean="factory" factory-method="getUser"></bean>
生命周期配置
生命周期:构造 -> 初始化->运行-> 销毁
配置多例的情况下,不会执行销毁
一般我们自己不会来配置这个生命周期。而这个基本上Spring自身来使用,例如在Spring操作连接池的时候,它会在DateSource销毁的时候执行。
User类
public class User {
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁");
}
}
配置信息
<bean id="user" class="cn.itdemo.test.User" init-method="init" destroy-method="destroy" >
</bean>
代码实现
@Test
public void testGetBean() throws Exception {
AbstractApplicationContext context= new ClassPathXmlApplicationContext("application.xml");
User u = (User) context.getBean("user");
System.out.println(u);
u.setName("a");
System.out.println(u.getName());
context.registerShutdownHook();//关闭spring容器
}
3.1.4.Bean对象的作用域
scope属性:Spring中生成对象的作用范围
3.1.5.配置懒加载
1.Spring中所有bean对象全部懒加载【配置文件的根对象中添加default-lazy-init为true】
2.单个Bean对象懒加载
<bean id="user" class="cn.itdemo.test.User" lazy-init="true"></bean>
3.2. BeanFactory
Spring是一个容器,它会根据配置为咱们创建相应的bean(对象)。
Spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。对象的创建使用懒加载【延迟加载】
3.2.1.根据ID获取对象
@Test
public void testGetBean2() throws Exception {
/**
* 需求:获取对象
* 1.获取配置文件
* 2.获取工厂对象
* 3.获取对象
*/
ClassPathResource resource = new ClassPathResource("application.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
User u = (User) factory.getBean("user");
System.out.println(u);
}
3.2.2.根据ID和对象的字节码对象
@Test
public void testGetBean3() throws Exception {
/**
* 需求:根据id和字节码对象获取对象
*/
ClassPathResource resource = new ClassPathResource("application.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
User user = factory.getBean("user",User.class);
System.out.println(user);
}
3.2.3.根据字节码对象获取【当前方式,在配置文件中获取的对象只能配置一次】
@Test
public void testGetBean4() throws Exception {
/**
* 需求:根据字节码对象获取对象
*/
ClassPathResource resource = new ClassPathResource("application.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
User user = factory.getBean(User.class);
System.out.println(user);
}
3.3.ApplicationContext
ApplicationContext的中文意思是“应用前后关系”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。对象的创建使用预加载【迫切加载】方式。
ApplicationContext是建立在BeanFactory基础上的一种更高层次的Spring IoC容器,其除了具有普通BeanFactory的全部功能以外,还加入了以下功能:
提供了文本信息解析工具,包括I18N的支持
提供了载入文件资源的通用方法
提供了发送事件的功能
要使用ApplicationContext还需要额外jar包,使用如下jar包:
spring-context-4.1.2.RELEASE.jar
spring-expression-4.1.2.RELEASE.jar
3.3.1.获取对象
@Test
public void testGetBean() throws Exception {
ApplicationContext context= new ClassPathXmlApplicationContext("application.xml");
User u = (User) context.getBean("user");
System.out.println(u);
System.out.println(u.getName());
}
3.3.2.和BeanFactory的区别
解释:都是接口,ApplicationContext是BeanFactory的子接口,拥有更多的功能与方法
重点:ApplicationContext是在启动容器创建上下文环境的时候就创建Bean对象(预先加载,迫切加载),而BeanFactory是在使用的时候才进行对象的创建(懒加载)
4.Spring测试
Spring测试主要是讲SpringJunit,这个Spring自己专门写的一套测试框架功能。
使用Spring框架测试(由Spring来接管测试功能)
三大框架整合的时候如果Spring的配置文件不能读取,那么整个项目是跑不起来的,而Spring的测试可以让我们在不启动服务器的情况下,就把相应的项目跑起来。
可以在不启动服务器的情况下,自动读取相应的配置文件。
4.1.导入jar包
spring-test-4.1.2.RELEASE.jar 测试包
spring-aop-4.1.2.RELEASE.jar AOP包
4.2.测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("bean.xml")
public class SpringTest {
@Autowired
private ApplicationContext context;
@Autowired
private UserTest user;
@Test
public void tesGetBean() throws Exception {
user.setName("测试");
System.out.println(user);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
使用何种Junit环境进行Spring测试,当前使用SpringJunit4ClassRunner的字节码对象
@ContextConfiguration("bean.xml")
加载Spring的配置文件,分以下写法
@ContextConfiguration("bean.xml")
默认加载当前包下的bean.xml文件
@ContextConfiguration("classpath:bean.xml")
加载当前src下的bean.xml文件
@ContextConfiguration("/bean.xml")
加载当前src下的bean.xml文件
@ContextConfiguration
加载当前测试类下的配置文件,文件命名必须是【类名-Context.xml】
@Autowired
将Spring里的对象注入到指定的位置
5.属性注入
Spring中的对象都是由Spring来统一管理,但是在对象中还存在属性,这些属性实际上引用的也是别的对象,那么这些对象也是由Spring来管理的。我们需要给Spring中的属性字段赋值,这称为属性注入。Spring支持的属性注入的方式有:set方法注入和有参构造方式。
5.1.set方式注入
User类
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
配置文件【若注入的是对象property中则使用ref属性】
<bean id="user5" class="cn.itdemo.test.spring.User" >
<property name="name" value="set方式"></property>
</bean>
测试代码
@Autowired
private User u;
@Test
public void testSet() throws Exception {
System.out.println(u.getName());
}
5.2.有参构造注入
User类
public class User2 {
private String name;
public String getName() {
return name;
}
public User2(String name) {
this.name = name;
}
public User2() {
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
配置文件【若注入的是对象property中则使用ref属性】
<bean id="user6" class="cn.itdemo.test.spring.User2" >
<constructor-arg name="name" value="有参构造"></constructor-arg>
</bean>
测试代码
@Autowired
private User2 u2;
@Test
public void testConstructor() throws Exception {
System.out.println(u2.getName());
}
5.3.Spring配置连接池
5.3.1.导入jar包
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
mysql-connector-java-5.1.26-bin.jar
5.3.2.配置BasicDataSource对象
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 查找当前src下查找jdbc.properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
5.3.3.jdbc.properties文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/user
jdbc.username=root
jdbc.password=root
注意事项,username一定要加前缀【jdbc.】,不要会出现问题。因为username已经被Spring在使用,会导致咱们的username失效,产生错误!当然也可以通过配置的形式解决该错误
<context:property-placeholder location="classpath:jdbc.properties" system-properties-mode="NEVER" />
但是该种方式其实没有太大的必要。
5.3.4.测试代码
@Autowired
private BasicDataSource dataSource;
@Test
public void testGetConnection() throws Exception {
System.out.println(dataSource.getConnection());
}
6.三层架构
开发把整个操作分成三层:
表现层(Web,GUI,…) 现在咱们做的jsp/servlet(struts2)就是开发表现层
业务层(service) 处理相应的业务,由表现层调用,现在咱们还未加上
Service层的构建和DAO层构建一样,分为接口包和实现包
持久层(dao) 做数据的持久化(现在咱们操作数据库就是完成持久化的功能)
JDBC,SpringJDBC,Hibernate,MyBatis