📄 15. spring note.txt
字号:
day1
什么是Spring?
开源、轻量级
Spring 特征:
1.B/S 和 C/S,使用资源小
2.对象间的关系松,高内聚,低耦合
IOC --- Inverse of control
使得业务组件都处在框架的管理之下
框架可以管理组件的创建和依赖关系
框架可以提供可以配置的服务
3.通过AOP技术将业务与非业务分离
AOP --- Aspect Oreinted Programming
在不修改组件的前提下,为组件提供扩展的服务
4.Spring容器管理整个JavaBean生命周期
简化对j2ee技术的使用
5.与Hibernate、Struts一样是个框架
(类集合) (框架提供)
6.Spring是一个全方位的框架
SpringMVC 类似 Struts
Spring框架在多层开发中位于那一层?或哪几层?
框架简化开发过程,提供公共服务和便利的工具
1.业务逻辑层 (Ioc *AoP) 最擅长的一层
2.表现层 (SpringMVC Web B/S都有)
3.数据持久层 (SpringDAO ORM)
什么是IoC:
1.IOC --- Inverse of control (控制反转)
A主动创建B的实例:正向控制
过去:拉模型
组件决定自己依赖的对象的创建
接口没有在松散耦合中起到太大作用
IOC:推模型,也叫做依赖注入
采用工厂模式管理应用组件的创建,管理组件的依赖关系
用接口表达组件间的依赖
依赖注入的方式
1)构造方法注入
2)set 方法注入
2.Spring IoC 容器先创建B的实例,再把B的实例注入A中
3.执行过程:
1)执行 BeanFactory 或 ApplicationContext 时,解析 xml 文件
2)通过反射,执行 JavaBean 的空参构造方法,创建实例
3)调用 JavaBean 的 set方法,将xml的信息注入到这 JavaBean 实例
或者执行满参构造方法创建实例,同时注入 xml 的信息
spring 框架的7个组成部分
1.BeanFactory -- (低级容器,接口)使用工厂模式实例化组件,装配组件
XmlBeanFactory(实现类)
2.ApplicationContext (高级容器,接口)--- bean factory 增加事件发布,增加了国际化,资源访问等的支持
ClassPathXmlApplicationContext(实现类)
3.aop -- 提供一种基于声明方式的AOP
4.dao 支持--简化jdbc,声明的事务
5.orm 支持-- 简化使用 Hibernate ,toplink 等持久化框架,方便的事务管理
6.web 支持-- 在 web 应用中使用 spring 框架的相关支持,协调表现层和业务层的关系
7.web mvc--- 独立的 web mvc 框架
spring 是全方位的框架
spring 的组成部分相对独立,可选择的使用
作业:
用户注册页面
要求: Servlet + Spring + JDBC + MySQL
1.判断用户名是否已注册(保证用户名唯一性)
2.采用B/S架构,使用IoC功能,完成JavaBean的注入。
在JavaBean不要使用 new 方式创建对象。
3.连接数据库时的 driver ,配置在 xml 文件中。
day2
二、控制反转(inverse of control IOC )
2、Bean 工厂(BeanFactory)的功能和配置
ClassPathResource
在类路径下查找资源
另有 FileSystemResource
XmlBeanFactory
读取 xml 文件中的配置信息
生产bean
解决bean 依赖
* Bean 的创建
spring 可调用bean的构造方法,或通过工厂方法生产 bean 对象
1.利用 bean 的构造方法创建bean
无参的构造方法
<bean id="refName" class="foopak.FooClass">
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
有参的构造方法,需指明构造方法的参数列表,通过:
<bean id="refName" class="foopak.FooClass">
<construct-arg><value>arg0</value></construct-arg>
<construct-arg><value>arg1</value></construct-arg>
</bean>
表明调用了两个参数的构造方法
2.通过工厂方法获得 bean 对象
bean 没有公共的构造方法,需通过工厂类或工厂实例来创建
分为静态工厂和实例工厂方法两种情况
静态工厂方法:
class 指明工厂类,factory-method 指明工厂方法
如: Connection con=DriverManager.getConnection(url,user,pwd);
对应的配置:
<bean id="con" class="java.sql.DriverManager" factory-method="getConnection">
<construct-arg><value>jdbc:mysql://localhost/test</value></construct-arg>
<construct-arg><value>zhangsan</value></construct-arg>
<construct-arg><value>pwd</value></construct-arg>
</bean>
工厂方法参数和构造方法参数设置的形式相同
实例工厂方法:
要先创建工厂实例,然后再由工厂实例创建产品
如: Statement stmt = con.createStatement();
con 对象是工厂
stmt 对象是产品
配置为:
<bean id="con" class="java.sql.DriverManager" factory-method="getConnection">
……
</bean>
<bean id="stmt" factory-bean="con" factory-method="createStatement"/>
单例 bean
bean 工厂生产bean 缺省都是单例的
scope 属性
scope="singleton|prototype|request|session"
后两者用于web应用中
通过注入解决bean的依赖
1 依赖注入的两种方式
1) set 注入
<property name="xxxYy">
……
</property>
相当于 setXxxYy(val);
2) 构造方法注入
<construtor-arg>……</construtor-arg>
spring 直接利用了 bean 的 set 或 构造方法
避免了使用接口注入的侵入性
2 依赖的目标类型分成三种形式:
1) 基本类型+String
<value>data</value>
类型自动转化
2) 对其他bean 的引用
<ref bean="target"/>
3) 集合类型
list
props
set
map
3 让spring 自动装配bean,解决依赖
autowire 属性指明自动装配的依据:
byName--- id=property
byType--- 属性的类型=当前工厂中bean的类型
constructor--构造方法参数的类型=当前工厂中bean的类型
autodetect-- constructor ---> byType
autowire-candidate 属性
指明是否作为 autowire 的候选对象
解决多个候选对象的冲突
true ---
false ---
4 让容器检测 bean 所有的依赖是否都已经满足
某个 bean 需要设置好所有属性
防止遗漏装配,在运行后出现莫名奇妙的情况
dependency-check 属性指明应检查的目标类型
simple -- 基本类型+字符串+集合
objects --- 对其他bean的依赖
all
none -- 默认值
管理 Bean 生命周期
生命周期
构造
set
回调初始化方法
getBean 返回
回调方法:
两个属性指明
init-method
destroy-method
或实现两个接口:
InitiallizingBean
DisposableBean
重用 bean 定义
parent -- 继承 bean 定义
bean 之间不一定有继承关系
abstract --- 只作为模板,不可以被实例化
补充:
name
id=""
name="/myBean"
name="a b c"
延迟加载bean
bean 的加载时机
预先加载
构造 bean 工厂时实例化所有bean
延迟加载
getBean 时构造
先构造依赖的bean
BeanFactory 总是延迟加载的
ApplicationContext
BeanFactory 的扩展
预先加载 单例 bean
lazy-init (true|false)
3、ApplicationContext
BeanFactory 的扩展,为应用提供国际化和事件框架的支持
1)I18N(国际化)
ApplicationContext 可以读取国际化的消息文件
getMessage();
实施:
1)注册消息源
<bean id="messageSource"
class="ResourceBundelMessageSource">
<property name="basename">
<value>MessageResource</value>
</property>
</bean>
bean 的id 必须是"messageSource"
2)读取消息
ApplicationContext 的方法:
getMessage(String key,String[] args,Locale l);
key - 消息的key
args- 插入到消息中的参数
l - 区域
Locale 语言和区域代码的封装对象
locale=new Local("zh","CN");
local=Locale.getDefault();
思考:工厂管理的组件怎样使用获得国际化消息
注意:因为AppicationContext包含了BeanFactory所有的功能,所以优先选择 ApplicationContext
2)事件框架
提供了一个观察者模式的框架,快速实现组件间的事件通知
实施:
1 所有想得到通知的对象都实现ApplicationListener
2 事件源发出事件:applicationContext.publishEvent(event);
自定义事件类
什么时候需要?
被观察者在需要传输数据给观察者时
怎么做?
自定义事件类 extends ApplicationEvent
day3
三、面向切面编程(Aspect oriented Programming)
1、代理模式
定义
1 A , B 实现了相同的接口,接口要求方法 m
2 用户调用A的m,A又调用B的m
解决什么问题(什么时候考虑使用代理模式)
1 扩展功能,而不修改现有的类
2 职责具有清晰的划分
怎么用
Actale--接口 方法 act
Actor---实现
Test --- 客户
Broker--实现,Actor 的代理
采用代理实现日志
IFoo
doA,doB,doC
Foo
Test -- Test
FooLogProxy
注意思考:日志代理的弊端
相同的代码散落在每一个方法中
2、使用动态代理解决
下面方法可以直接为接口 Foo 产生代理实例:
Foo proxy = (Foo) Proxy.newProxyInstance(
Foo.class.getClassLoader(),
new Class[]
{ Foo.class },
handler);
对 proxy 调用接口定义的方法,都会被分发给:
handler.invoke()
handler 是实现InvocationHandler 接口的实例
这样就把对多个方法的调用集中起来了
handler.invoke()然后再分发请求到目标方法
实施:
1) 实现 InvocationHandler 接口
2)产生代理
3、Spring 的AOP 采用动态代理实现
一些别扭的概念:
切面:当前关注的一个代码的流程,其中可能调用了多个类的多个方法。
连接点:一个代码流程中的某个步骤,也就是这个代码流程中对某个方法的调用。
通知(Advice):对于某个方法(连接点),进行拦截的拦截规则。
切入点:对于某个方法(连接点),是否被拦截的判断(过滤)规则。
目标对象:某个连接点所在的对象。
AOP代理:目标对象的代理。
代理的生成:ProxyFactoryBean(org.springframework.aop.framework.ProxyFactoryBean)
工厂类,生产代理
区别于 BeanFactory
InvocationHandler 的行为 : Advice
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -