Java框架(四)之Spring(概述、Ioc、DI)
一、Spring框架概述
1.定义
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson开发。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架
2.核心
Spring的核心是控制反转(IoC)和面向切面(AOP)
3.分层
web层:struts,spring-MVC
service层:spring 事务控制 spring
dao层:hibernate,mybatis , jdbcTemplate(spring提供了一个模板对象) --> spring-data
4.优点
-
方便解耦,简化开发 (高内聚低耦合)
• Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
• spring工厂是用于生成bean (静态工厂模式)
• spring的IoC(控制反转)底层用到什么设计模式?-- 静态工厂模式 -
AOP编程的支持
• Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
• aop的底层运用到什么设计模式? – 动态代理 -
声明式事务的支持 (AOP 动态代理)
• 只需要通过配置就可以完成对事务的管理,而无需手动编程 -
方便程序的测试
• @RunWith(SpringJUnit4ClassRunner.class)
• @ContextConfiguration(“applicationContext.xml”) - 方便集成各种优秀框架
- 降低JavaEE API的使用难度
5.体系结构
二、IoC(掌握)
1.导入jar包
<!-- spring依赖
四个核心(beans+core+expression+context)+依赖(commons-logging)
-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
2.目标类
- 提供UserService接口和实现类
- 获得UserService实现类的实例
3.配置文件
- 位置:任意,开发中一般在classpath下(src)
- 名称:任意,开发中常用applicationContext.xml 不是必须的。
- 内容:添加schema约束
约束文件位置:spring-framework-XXX.RELEASE\docs\spring-framework-reference\html\ xsd-config.html
4.测试
//创建ApplicationContext对象
ApplicationContext aContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//根据spring的核心对象解析applicationContext.xml配置文件 从配置文件中获取一个UserService 对象
//从spring的配置文件中获取对象的三种方式
//方式一:根据对象的class
UserService userService = aContext.getBean(UserService.class);
//单词写错:NoSuchBeanDefinitionException: No bean named 'userService11' available
UserService userService2 = (UserService) aContext.getBean("userService");
UserService userService3 = (UserService) aContext.getBean("us");
System.out.println(userService==userService2);
三、DI 依赖注入
1.定义
DI Dependency Injection ,依赖注入 类与类之间的依赖关系,由spring通过spring注入 —依赖注入
依赖:一个对象需要使用另一个对象
注入:通过setter方法(或其他方式)进行另一个对象实例设置。
2.模拟spring执行
<!-- 1.dao
等价于: BookDao bookDao = new BookDaoImpl();
-->
<bean id="bookDao" class="com.itqf.di.dao.impl.BookDaoImpl"></bean>
<!-- service
等价于:
BookService bookService = new BookServiceImpl();
bookService.setBookDao(bookDao);
-->
<bean id="bookService" class="com.itqf.di.service.impl.BookServiceImpl">
<!-- 注入dao -->
<property name="bookDao" ref="bookDao" ></property>
</bean>
3.schema xml提示
- 步骤一:确定xsd文件位置
- 步骤二:复制路径
- 步骤三:搜索“xml catalog”
- 步骤四:添加约束提示
4.核心api
- BeanFactory :这是一个工厂,用于生成任意bean。 创建对象
采取延迟加载,第一次getBean时才会初始化Bean - ApplicationContext:是BeanFactory的子接口,功能更强大。当配置文件被加载,就进行对象实例化。
(1)ClassPathXmlApplicationContext 用于加载classpath(类路径、src)下的 xml 加载xml运行时位置 --> /WEB-INF/classes/…xml
(2)FileSystemXmlApplicationContext 用于加载指定盘符下的xml
加载xml运行时位置 --> /WEB-INF/…xml
通过java web ServletContext.getRealPath() 获得具体盘符
5.实例化Bean 基于XML
三种:默认构造、静态工厂、实例工厂
(1)默认构造<bean id="" class="">
必须提供默认构造
(2)静态工厂
常用与spring整合其他框架(工具)
静态工厂:用于生成实例对象,所有的方法必须是static
<bean id="" class="工厂全限定类名" factory-method="静态方法">
(3) 实例工厂
-
实例工厂:必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。
<bean id="myBeanFactoryId" class="工厂对象全路径 "></bean> <!-- 获得userservice * factory-bean 确定工厂实例 * factory-method 确定普通方法 --> <bean id="userServiceId" factory-bean="myBeanFactoryId" factory-method="createService"></bean>
6.作用域
-
作用域:用于确定spring创建bean实例个数
spring:bean:默认是单例
bean标签有scope属性可以设置bean的作用域。 -
取值:
singleton 单例,默认值。
prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。 -
配置信息
7.生命周期
初始化和销毁
8.依赖注入
- 依赖注入方式:手动装配 和 自动装配
1.手动装配
(1)构造器注入<constructor-arg>
用于配置构造方法一个参数argument
name :参数的名称
value:设置普通数据
ref:引用数据,一般是另一个bean id值
index :参数的索引号,从0开始 。如果只有索引,匹配到了多个构造方法时,默认使用第一个。
type :确定参数类型
(2)setter注入
普通数据
<property name="" value="值">
等效
<property name=""> <value>值</value>
引用数据
<property name="" ref="另一个bean">
等效
<property name="">
<ref bean="另一个bean"/>
(3)p标签注入
p命名空间使用前提,必须添加命名空间
<bean id="userService" class="com.itqf.bean.p.UserServiceImpl" p:userDao-ref="userDao" >
</bean>
<bean scope="prototype" id="userAction" class="com.itqf.bean.p.UserAction" p:userService-ref="userService"></bean>
(4)集合注入
<bean id="myCollection" class="com.itqf.bean.collection.MyCollection" autowire="default">
<property name="name" value="天线宝宝"></property>
<!-- 数组 -->
<property name="arr">
<array>
<value>张三</value>
<value>lisi</value>
<value>王苏</value>
</array>
</property>
<!-- 集合 -->
<property name="list">
<list>
<value>basketball</value>
<value>football</value>
<value>pingpongball</value>
</list>
</property>
<!-- set -->
<property name="set">
<set>
<value>宝马</value>
<value>劳斯莱斯</value>
<value>法拉利</value>
<value>宾利</value>
<value>QQ</value>
</set>
</property>
<!-- Map -->
<property name="map">
<map>
<entry>
<key><value>1001</value></key>
<value>张三</value>
</entry>
<entry>
<key><value>1002</value></key>
<value>李四</value>
</entry>
<entry>
<key><value>1003</value></key>
<value>赵六</value>
</entry>
</map>
</property>
<!-- properties 类型 -->
<property name="properties">
<props>
<prop key="jdbc.driverClass">com.mysql.jdbc.Driver</prop>
<prop key="jdbc.url">jdbc:mysql://localhost:3306/book</prop>
</props>
</property>
</bean>
9.使用注解
1.常用注解
创建对象
@Component
@Repository
:dao层@Service
:service层@Controller
:web层
注入@Autowired
按照类型注入 (spring提供)@Qulifer()
配合Autowired 使用(用的少)@Resource()
按照名称注入 (jdk)
生命周期
初始化:@PostConstruct
销毁:@PreDestroy
作用域@Scope("prototype")
多例
2.依赖注入(给私有字段设置,也可以给setter方法设置)
方式1:按照【类型】注入 @Autowired
方式2:按照【名称】注入2 @Resource( name="名称")
方式3:按照类型注入(autowired)时,如果有两个匹配结果,会报错可以使用如下解决方案: @Qualifier("userServiceImpl2")
注意:@Qualifier
不能当独使用,一般配合autowired使用
3.扫描含有注解的包
<context:component-scan base-package="com.qf.annotation"></context:component-scan>
4.属性有关的注解
@value
注入属性值
1、加在成员变量上:通过反射的Field赋值(破坏对象的封装性)
2、加在set方法上:通过set方法赋值@Value
直接读取properties文件中的内容
10. Spring整合JUnit4测试
1.导包
<!-- spring+junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2.创建测试类
//创建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定创建容器时使用哪个配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class RunWithTest {
//将名为user的对象注入到u变量中
@Resource(name="person")
private Person p;
@Test
public void testCreatePerson(){
System.out.println(p);
}
}