Spring
Spring是个开源的框架,解决企业应用开发的复杂性而创建,是一个轻量级的控制反转 (IOC) 和面向切面 (AOP) 的容器框架
框架的特点: 半成品,封装了特定的处理流程和控制逻辑
框架和类库的区别 框架封装了控制逻辑和处理流程是高内聚的,框架专注于某个领域,而类库是松散的工具组合,类库更加的通用
IOC(控制反转) :控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建和维护
IOC(又名 依赖注入) :由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中
IOC的使用过程 1.找IOC容器 2.日期返回对象 3.使用对象
Spring的优势
- 方便解耦,简化开发
- AOP编程的支持
- 方便进行面向切面编程,许多不容易用传统的OOP实现的功能可以通过AOP轻松实现
- 声明式事务的支持
- 从事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量
- 方便程序测试
- 可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
- 方便集成各种优秀的框架
- Spring对各种优秀框架( Struts, Hibemate, Hessian, Quartz等) 的支持
- 降低JavaEE API的使用难度
- Spring对JavaEE API 进行了薄薄的封装层,使这些API的使用难度大为降低
Spring快速入门
- Spring开发步骤
- 导入Jar包
- 创建Bean
- 创建applicationContext.xml
- 在配置文件中进行配置
- 创建ApplicationContext对象getBean
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
}
Spring配置文件
- Bean标签基本配置
- 用于配置对象交由Spring来创建
- 默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
- 基本属性 :
- id : Bean实例在Spring容器中的唯一标识
- class : Bean的全限定名称
- scope : 指对象的作用范围,取值如下 :
- singleton : 默认值,单例的
- prototype : 多例的
- request : WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中
- session : WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中
- global session : WEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于session
- 生命周期属性配置
- init-method : 指定类中的初始化方法名称
- destory-method : 指定类中销毁方法名称
- Bean实例化三种方式
- 无参构造方法实例化
- < bean id=“userDao” class=“dao.impl.UserDaoImpl”/>
- 工厂静态方法实例化
- 工厂实例方法实例化
- 无参构造方法实例化
- Bean的依赖注入概念 :
- Spring框架核心IOC的具体实现
- 将对象的创建权交给Spring,业务层和持久层的依赖关系,由Spring来维护,由Spring将持久层对象传入业务层,而不用我们自己去获取
- Spring框架核心IOC的具体实现
- Bean的依赖注入方式
- 构造方法 :
- set 方法 :
- Bean的依赖注入的数据类型 :
- 除了可以进行对象的引用注入,普通的数据类型和集合等都可以在容器中进行注入
- 注入数据的三种数据类型 :
- 普通数据类型
- 引用数据类型
- 集合数据类型
<!--普通的对象注入
<bean id="userDao" class="dao.impl.UserDaoImpl" ></bean>
静态工厂注入
<bean id="userDao" class="factory.StaticFactory" factory-method="getUserDao" ></bean>
-->
<!-- //动态工厂
<bean id="factory" class="factory.DynamicFactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>
-->
<!-- 普通数据类型注入
<bean id="userDao" class="dao.impl.UserDaoImpl" >
<property name="username" value="zhansan"/>
<property name="age" value="18"/>
</bean>-->
<bean id="userDao" class="dao.impl.UserDaoImpl" >
<property name="strlist" >
<list>
<value>aaa</value>
<value>aaa</value>
<value>aaa</value>
</list>
</property>
<property name="userMap">
<map>
<entry key="u1" value-ref="user1"></entry>
<entry key="u2" value-ref="user2" ></entry>
</map>
</property>
<property name="pro">
<props>
<prop key="p1">pp1</prop>
<prop key="p2">pp2</prop>
<prop key="p3">pp3</prop>
</props>
</property>
<property name="age" value="18"/>
</bean>
<bean id="user1" class="domain.User">
<property name="name" value="zhansan"></property>
<property name="addr" value="beijing"></property>
</bean>
<bean id="user2" class="domain.User">
<property name="name" value="zhann"></property>
<property name="addr" value="beijing"></property>
</bean>
<!--//set注入
<bean id="userService" class="service.impl.UserServiceImpl" >
<property name="userDao" ref="userDao"></property>
</bean>-->
<!--有参数构造注入-->
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
- 引入其它配置文件(分模块配置)
- 实际开发中,Spring的配置内容非常多,这就导致Spring配置很杂,所以可以将部分配置文件拆解到其它配置文件中,而在Spring主配置文件中通过import标签进行加载
< import resource = " applicationContext-xxx.xml ">
- 实际开发中,Spring的配置内容非常多,这就导致Spring配置很杂,所以可以将部分配置文件拆解到其它配置文件中,而在Spring主配置文件中通过import标签进行加载
- Spring相关的API
- ApplicationContext的继承体系
- 接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
- 实现类
- ClassPathXmlApplicationContext : 从类的根路径下加载配置文件推荐使用
- FileSystemXmlApplicationContext : 从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
- AnnotationConfigApplicationContext : 当使用注解配置容器对象时,需要使用此类来创建spring容器,它用来读取注解
- ApplicationContext的继承体系
- getBean()方法使用
- getBean( “id” )
- getBean(磁盘上的xml文件路径)
Spring配置数据源
- 数据源(连接池)的作用
- 数据源是为了提高程序性能而出现的
- 实现实例化数据源,初始化部分连接资源
- 使用连接资源时从数据源中获取
- 使用完后将连接资源归还数据源
- 数据源开发步骤
- 导入Jar包
- 创建数据源对象
- 设置数据源的基本连接数据
- 使用数据源获取连接资源和归还连接资源
- 配置数据源
- 抽取jdbc配置文件
- 首先,需要引入context命名空间和约束路径
- 命名空间 : xmlns:context=“http://www.springframework.org/schema/context”
- 约束路径 :
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd - Spring容器加载properties文件 : < context:property-placeholder location=“classpath:jdbc.properties” />
- 首先,需要引入context命名空间和约束路径
- 抽取jdbc配置文件
<?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" >
<!-- 加载外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="url" value="${url}"></property>
<property name="driverClassName" value="${driver}"></property>
</bean>
</beans>
测试使用的代码 :
//测试容器产生数据源对象
@Test
public void test3() throws Exception {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = app.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
Spring注解开发 :
- Spring原始注解 : 主要是替代< Bean > 的配置
- @Component : 使用在类上用于实例化Bean
- @Controller : 使用在web层的类上用于实例化Bean
- @Service : 使用在service层的类上用于实例化Bean
- @Repository : 使用在dao层的类上用于实例化Bean
- @Autowired : 使用在字段上用于根据类型依赖注入
- @Qualifier : 结合@Autowired一起使用用于根据名称进行依赖注入
- @Resource : 相当于@Autowired + @Qualifier,按照名称进行注入
- @Value : 注入普通属性
- @Scope : 标注Bean的作用范围
- @PostConstruct : 使用在方法上标注该方法是Bean的初始化方法
- @PreDestory : 使用在方法上标注该方法是Bean的初始化方法
配置组件扫描 : < context:component-scan base-package=“annocation”/>
UserDaoImpl类 :
//<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
@Component("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userdaoimpl");
}
}
UserServiceImpl类 :
//<bean id="userService" class="service.impl.UserServiceImpl"> </bean>
@Component("userService")
public class UserServiceImpl implements UserService {
//<property name="userDao" ref="userDao"></property>
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
xml配置组件扫描 :
<!-- 注解组件扫描 -->
<context:component-scan base-package="annocation"/>
- Spring新注解
- @Configuration : 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注释
- @ComponentScan :
- 用于指定Spring在初始化容器时要扫描的包
- 作用和在Spring的xml的配置文件中的 < context:component-scan base-package=“annocation”/>一样
- @Bean : 使用在方法上,标注将该方法的返回值存储到Spring容器中
- @PropertySource : 用于加载properties文件中的配置
- @import : 用于导入其他配置类
SpringConfiguration是主配置类
//标志该类是Spring的核心配置类
@Configuration
@ComponentScan("annocation")
@Import(DataSourceConfiguration.class)
public class SpringConfiguration {
}
DataSourceConfiguration配置类不是主配置类,提供给
@Configuration
@ComponentScan("annocation")
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
@Value("${driver}")
private String driver;
@Value("${username}")
private String username;
@Value("${url}")
private String url;
@Value("${password}")
private String password;
@Bean("dataSource")//Spring会将当前方法的返回值以指定名称存储到Spring容器中
public DataSource getdatasource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setDriverClassName(driver);
return dataSource;
}
}
运行代码 : UserController类
package annocation.web;
import annocation.config.SpringConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import annocation.service.UserService;
public class UserController {
public static void main(String[] args) {
//ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService bean = app.getBean(UserService.class);
bean.save();
}
}
Spring整合Junit
- 原始Junit测试Spring的问题 :
- 每个测试类中都需要存在两行代码 :
ApplicationContext app = new ClassPathXmlApplicationContext(“applicationContext.xml”);
DataSource dataSource = app.getBean(DataSource.class); - 两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常,所以也不能轻易删除
- 每个测试类中都需要存在两行代码 :
- 解决思路 :
- 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
- 将需要进行测试Bean直接在测试类中进行注入
- Spring集成Junit步骤 :
- 导入spring集成Junit的坐标
- 使用@Runwith 注解替换原来的运行期
- 使用@ContextConfiguration指定配置文件或配置类
- 使用@Autowire 注入需要测试的对象
- 创建测试方法进行测试
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
@Autowired
//@Qualifier("userService")
private UserService userService;
@Test
public void test1(){
userService.save();
}
}