框架-Spring
一、Spring框架概述
1、Spring是轻量级的开源的javaEE框架。
2、Spring可以解决企业应用开发的复杂性。
3、Spring的核心:IOC,AOP
- IOC:控制反转(Inversion of Control),把创建对象的过程交给Spring容器进行管理
- AOP:面向切面,不修改源代码进行功能增强
4、Spring特点
- 方便解耦,简化开发
- AOP编程支持
- 方便程序测试(junit)
- 方便和其他框架进行整合(mybatis)
- 降低API开发难度
- 方便进行事务操作
二、入门案例
Spring架构图
ioc基本包下载
IOC基本包有这5个:
GA表示稳定版本 ,选这个
SNAPSHOT表示快照版本
1 |
|
第一个是项目需要导入的jar包,javadoc是帮助文档,sources是源码文件
将jar包导入项目中
测试
文件结构:
测试代码:
1 |
|
三、Spring IOC
Spring 提供 IOC 容器两种实现方式:(两个接口)
- BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用 ,加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
- ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建,ApplicationContext 接口有实现类
Bean管理
Spring创建对象
Spring注入属性
Bean类型
1、普通bean
2、工厂bean
1 |
|
1 |
|
1 |
|
1 |
|
Bean作用域
在Spring中创建的bean默认是单实例的
1 |
|
可以在配置文件中设置这个bean是单实例的还是多实例的
scope 属性值
- singleton,默认值,表示是单实例对象
- prototype,表示是多实例对象
1 |
|
1 |
|
- 设置 scope 为 singleton 的时候,在加载 Spring 配置文件时候就会创建单实例对象
- 如果 scope 为 prototype 的时候,不是在加载 Spring 配置文件的时候创建对象,而是在调用 getBean 方法的时候创建多实例对象
Bean的生命周期
生命周期:从对象的创建到对象的销毁的过程。
过程:
(1)通过无参构造器创建bean实例
(2)通过set方法为bean的属性设置值和对其他bean的引用赋值
(3)调用bean的初始化方法
(4)bean可以使用了
(5)当容器关闭时,调用bean的销毁方法
想自己看整个流程需要在xml配置文件的bean配置中指定初始化和销毁方法
1 |
|
销毁的话需要在test测试类中context.close()
1 |
|
1 |
|
1 |
|
后置处理器的实现:定义一个类,实现BeanPostProcesser接口,重写before和after方法,在spring配置文件中配置后置处理器
Bean管理操作的方式
1、基于xml配置文件方式
(1)创建对象
1 |
|
在spring配置文件中,使用bean标签,标签里添加对应的属性,就可以实现spring帮我们进行对象创建。
bean标签中的属性:
- id:给对象起一个标识名字(唯一)
- class:类的全路径
创建对象时是利用类的无参构造方法。
(2)注入属性
DI:依赖注入,即注入属性。
第一种注入方式:使用set方法进行注入
1 |
|
1 |
|
第二种注入方法:使用有参构造器进行注入
1 |
|
1 |
|
第三种注入方式:p名称空间注入(可以说是set方法注入的简化版)
增加这个xmlns:p="http://www.springframework.org/schema/p"
1 |
|
给属性注入的值的类型
属性的类型是String或者基本数据类型 null
1
2
3<property name="bname" >
<null/>
</property>属性的类型是String或基本数据类型 特殊符号(< >)
1
2
3
4
5
6
7<property name="bname" >
<value>
<![CDATA[<<南京>>]]>
</value>
</property>
<!-- 输出 <<南京>> -->属性是引用数据类型(对象) 注入外部bean
外部bean:直接在beans标签内部直接定义的bean对象,外部bean可以被多个bean对象引用
1
2
3
4
5
6
7
8
9
10
11
12public class userService {
private spring5.vickkkyz.Dao.userDao userDao;
public void setUserDao(spring5.vickkkyz.Dao.userDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("userService.....");
userDao.add();
}
}1
2
3
4
5public class userDao {
public void add(){
System.out.println("userDao.....");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<?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">
<bean id="service" class="spring5.vickkkyz.Service.userService">
<property name="userDao" ref="dao"></property>
</bean>
<bean id="dao" class="spring5.vickkkyz.Dao.userDao"></bean>
</beans>
<!-- 这样写就是级联赋值了
<bean id="service" class="spring5.vickkkyz.Service.userService">
<property name="userDao" ref="dao"></property>
</bean>
<bean id="dao" class="spring5.vickkkyz.Dao.userDao">
<property name="name" value="这是内部bean的案例"></property>
</bean>
-->
<!--
<bean id="service" class="spring5.vickkkyz.Service.userService">
<property name="userDao" ref="dao"></property>
<property name="userDao.name" value="这是内部bean的案例"></property> //写这个需要写get方法
</bean>
<bean id="dao" class="spring5.vickkkyz.Dao.userDao">
</bean>
-->属性是引用数据类型(对象) 注入内部bean
内部bean:在某个bean标签的内部定义的bean对象,内部bean只能被某个对象的某个属性引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14<?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">
<bean id="service" class="spring5.vickkkyz.Service.userService">
<property name="userDao">
<bean id="dao" class="spring5.vickkkyz.Dao.userDao">
<property name="name" value="这是内部bean的案例"></property>
</bean>
</property>
</bean>
</beans>属性是数组类型、List类型、Map集合类型 注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class student {
private String[] courses;
private List<String> list;
private Map<String,String> map;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String toString() {
return "student{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", map=" + map +
'}';
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<bean id="student" class="spring5.vickkkyz.Collection.student">
<property name="courses">
<array>
<value>数组第一个元素</value>
<value>数组第二个元素</value>
</array>
</property>
<property name="list">
<list>
<value>集合第一个元素</value>
<value>集合第二个元素</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"></entry>
<entry key="key2" value="value2"></entry>
</map>
</property>
</bean>list元素是对象的情况下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Course {
private String cname;
private int cid;
public void setCname(String cname) {
this.cname = cname;
}
public void setCid(int cid) {
this.cid = cid;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
", cid=" + cid +
'}';
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<?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">
<bean id="student" class="spring5.vickkkyz.Collection.student">
<property name="list">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<bean id="course1" class="spring5.vickkkyz.Collection.Course">
<property name="cname" value="数学"></property>
<property name="cid" value="1"></property>
</bean>
<bean id="course2" class="spring5.vickkkyz.Collection.Course">
<property name="cname" value="英语"></property>
<property name="cid" value="2"></property>
</bean>
</beans>将集合注入部分抽取成公共部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-beans.xsd">
<util:list id="courselist">
<!-- 基本数据类型和String类型就直接用value标签来赋值-->
<!-- <value></value>-->
</util:list>
<bean id="student" class="spring5.vickkkyz.Collection.student">
<property name="list" ref="courselist"></property>
</bean>
</beans>自动装配
上面所有用的方式都是手动装配,即手动给类中的属性设置值。
只有非字面量(非基本数据类型及其封装类)的属性才能自动装配
比如现在有两个类A,B。在类A中有一个属性类B,在spring配置文件中配置类A,对于类A的属性B不需要手动配置,而是在bean标签内有一个atuowire标签 自动装配。(需要提前配置好类B)
自动装配类型:
- byName 注入值 bean 的 id 值和在类A中B的属性名称一样
- byType 根据属性类型注入
2、基于注解方式
注解的格式:@注解名称(属性名称=属性值,属性名称=属性值..)
注解是为了简化xml的配置
第一步:引入依赖包
commons-logging-1.2.jar
spring-aop-5.3.21.jar
spring-beans-5.3.21.jar
spring-context-5.3.21.jar
spring-core-5.3.21.jar
spring-expression-5.3.21.jar
第二步:开启组件扫描
1 |
|
自定义扫描
1 |
|
第三步:使用注解
1类相关的注解: Spring中针对bean管理中创建对象提供的注解有:
@Component
@Service
@Controller
@Repository
2 属性相关的注解
@Atuowired 按照类型(class)进行自动装配
@Qualifier 按照名称进行自动装配,需要和Autowired一起使用
@Resource 可以按照类型,也可以按照名称
@Value 对String类型的自动装配
1 |
|
完全注解模式:不用xml文件
使用配置类代替xml文件
1 |
|
测试类:
1 |
|
四、Spring AOP
AOP相关概念
面向切面编程,基于OOP面向对象编程,底层就是AOP在程序运行期间,将某段代码(日志代码)动态地切入(不把日志代码写死在业务逻辑方法中)到指定方法的指定位置(方法的开始,结束,异常等位置)进行运行的这种编程方式。
jdk默认的动态代理:如果目标对象没有实现任何借口,是无法为他创建代理对象的,因为jdk动态代理与目标对象就是靠实现同一个接口来建立的。
利用Spring AOP的优点:实现简单,没有强制要求目标对象必须实现接口
AOP使用步骤
1、导包
Spring基础包
commons-logging-1.2.jar
spring-aop-5.3.21.jar
spring-beans-5.3.21.jar
spring-context-5.3.21.jar
spring-core-5.3.21.jar
spring-expression-5.3.21.jar
AOP相关的包
spring-aop-5.3.21.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
2、写配置
1 |
|
myCalculator实现接口的情况下:
1 |
|
1 |
|
1 |
|
1 |
|
myCalculator没有实现接口的情况下:
由cglib来创建动态代理对象
1 |
|
3、测试
JdbcTemplate是Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作