Spring 设计是很好的,但Spring用起来是极为简单的。
---工厂模式---
23种设计模式之一。
简单工厂 不是23设计模式之一。
工厂方法 才是
抽象工厂 也是。
Spring的作者研究发现:
Java项目中,对象与对象经常形成调用栈。
A对象,调用B对象的方法,此时就成为 A 依赖 B。
对于初级编程来说,当A依赖B时,程序总是先创建B对象,再去调用B对象的方法。
这种做种的问题在于:
当被依赖的对象升级时,依赖于该对象的所有对象都需要修改、升级!
为了解决该问题,提出了工厂模式:
(1) 面向接口编程。
(2) 引入一个工厂类,它负责产生被依赖对象。
(3) 依赖对象调用工厂类的方法来获取被依赖对象,
这样就把依赖对象与被依赖对象的实现类分离了,
好处就是:
当被依赖的对象升级之后,依赖于该对象的所有对象都无需修改,只要修改工厂类即可。
工厂模式的坏处是什么?
虽然改得少了,但是工厂类还是需要修改!
Spring框架的核心:
1. Martine Fowler :DI(IoC:控制反转:Johnson)
2. AOP
3. Spring与ORM框架、MVC框架的整合。
Spring的用法更简单,因为它不仅可以在Web应用中使用,也可以在Java SE项目使用。
Spring的安装只要一步:复制JAR包。
Spring框架的用法:
1. 写一个Java类。(任意的Java类)。
2. 在Spring的配置文件中配置它。
为了获得Spring所创建的对象,也需要两步:
1. 创建Spring容器。 ApplicationContext代表,在Java SE项目中,有两个最常用实现类:
FileSystemXmlApplicationContext , ClassPathXmlApplicationContext
2. 调用Spring容器的getBean()方法。
用Spring与不用Spring的区别:
如果不用Spring,也不用工厂模式,所有对象都是通过new 来创建的。
用Spring之后,对象交给Spring去创建、管理,应用程序只要调用Spring容器的getBean()
IoC名词
不用IoC以前,程序自己去调用setter方法来获得被依赖的对象。
现在程序不调用了,而是让Spring框架以反射的方式去调用setter方法。
********************************
IoC容器就是工厂模式的演化,
所以Spring也需要面向接口编程,这样才能维持较好的可扩展性。
Spring:通过XML代码来控制执行Java代码。
********************************
依赖注入/控制反转
原来是由程序自己调用setter方法,为属性设置值。
用Spring之后,只要在spring文件中配置即可,由Spring负责为属性设置值。
设值注入:通过<property .../>元素来控制调用setter方法,由setter方法为属性注入值,
这就是设值注入。
构造注入:通过<constructor-arg .../>元素来控制调用有参数的构造器,由构造器方法为属性注入值,
这就是构造注入。
Spring容器中的Bean—— 所有的Java实例都可以是Bean!任何Java实例都可以。
Spring框架:用XML配置去驱动Java代码。
IoC/DI - 设值注入与构造注入。
bean - 调用构造器。
constructor-arg,设置构造参数。
property : 调用setter方法。
Spring的开发:
A。 写Java类。
B。 配置Java类。
Spring容器Bean的作用域:
通过bean元素的scope属性(默认为singleton)来指定:
-singleton - 保证Spring容器只会产生一个该Bean的实例。
-prototype - 相当于new
-request - Web应用才有效。同一次请求,Bean实例只有一个。
-session - Web应用才有效。同一次session,Bean实例只有一个。
-global session
对象的产生、销毁需要较大的系统开销,
经常地创建对象、销毁对象,必然造成系统性能的降低。
一般将scope设置singleton能保证较好的性能。
---调用setter方法---
<property .../>控制调用setter方法。
setter方法的形参类型
- 如果标量类型,为<property.../>指定value属性即可。
- 如果自定义类
A. 可为<property.../>指定ref属性,引用容器中已有的Bean。
B. 为 <property.../>指定嵌套Bean。
- Set/List/Map/Properties/数组
set/list/map/props/list子元素来配置参数值。
自动装配
autowire属性(默认是no)指定:
-no
-byName ,根据setter方法的名字来查找。
-byType
-constructor
-autodetect
创建Bean实例的方式:
1. 调用构造器来创建。
每个bean元素控制调用一次构造器。
2. 调用静态工厂方法来创建。
需要在<bean.../>元素增加factory-method属性。
如果工厂方法需要参数,用<constructor-arg.../>元素传入。
3. 调用实例工厂方法来创建。
需要在<bean.../>元素增加factory-method属性,不需要class属性,需要使用factory-bean属性。
如果工厂方法需要参数,用<constructor-arg.../>元素传入。
抽象Bean和Bean继承
(Spring每升级一次,配置文件就可以简化一次)
在有些情况,配置文件中有一批Bean,它们的某些配置是相同的。
此时就可以把这些相同的配置,抽取成“配置模板”,此时“配置模板”并不需要创建实例
为了控制Spring框架不创建实例,可以将它配置抽象Bean
所谓“抽象Bean”,其实就是“Bean模板”
Spring框架的本质:以XML配置来驱动执行Java代码。
你们现在会的:
1. 创建对象。
用无参数的构造器来创建。
用有参数的构造器来创建——增加<constructor-arg.../>
用工厂方法俩创建。
2. 调用setter方法。
工厂Bean(特殊的API)
静态工厂方法创建Bean/实例工厂方法创建Bean——都需要配置一个factory-method属性。
BeanFactory(ApplicationContext) 与 FactoryBean(工厂Bean)
当程序去获取工厂Bean时,实际上Spring返回的工厂Bean的getObject方法的返回值。
容器中Bean的生命周期
********************************************************************
什么时候初始化Bean实例?
如果使用BeanFactory作为Spring容器,容器初始化时不会初始化任何实例。
如果使用ApplicationContext作为Spring容器,容器初始化时会初始化所有singleton Bean的实例。
什么时候调用Bean的setter方法?
Bean实例一旦被创建,立即就会根据配置文件中property元素来调用她的setter方法
********************************************************************
当Singleton Bean依赖于非Singleton Bean时,
singleton Bean会把非singleton Bean变成单例行为。
为了解决这个问题,解决思路为:
(1)放弃依赖注入。
程序每次都主动去获取prototype Bean
——坏处是:每次都要先获取Spring容器,在调用容器的getBean方法。
(2)lookup注入。
<lookup-method.../>元素来控制, 该元素告诉Spring要重写某个方法。
重写的方法由name属性指定。
CGLIB - Code Generator lib
Spring本质:通过XML配置去驱动调用Java代码。
1. 创建对象。
2. 调用setter方法。
3. 调用getter方法? PropertyPathFactoryBean (哪个对象,哪个getter方法)
4. 访问Field值? FieldRetrievingFactoryBean (哪个对象/哪个类,哪个field)
5. 调用普通方法? MethodInvokingFactoryBean(哪个对象/哪个类,哪个方法,传入参数)
SpEL —— 进一步简化IoC容器的配置。
AOP
一个问题:
项目开发完成了,系统可能有1000个组件,每个组件包含10个方法...
客户端突然要求:权限控制——
先定义一个方法:auth()
客户端又突然要求:加日志——
先定义一个方法:log()
最后的解决方法就是:AOP,所谓AOP就是对原来的类,进行修改、增强。
第一种:在编译时就修改、增强:AspectJ
第二种:在运行时通过JDK动态代理,CGLIB这种动态地修改、增强:Spring AOP。
************************************************
编译型的语言?解释型语言?谁的速度快?
语言 → 翻译 → 机器指令。
源代码代码写好 → 编译 → 二进制的机器码。 直接执行二进制的机器码(编译型语言)
源代码代码写好 → 解释执行(编译 + 运行)。
************************************************
用合适的语法,提供足够的信息,驱使计算机为我们干活。
AspectJ更优秀~
性能更好,而且更符合AOP规范。
它的AOP关键:ajc命令,它在编译时进行增强——对目标类进行修改。
Spring AOP
依赖XML配置文件,然后用CGLIB在运行时进行增强——生成目标类的子类。
--AOP概念--
AOP: 面向切面编程。
Aspect - 切面。
Pointcut - 切入点。
Advice - 增强处理 / 通知(建议)
AOP代理 - AOP框架所生成新的类的实例。
目标对象 - 未增强的类的对象。
织入
对于AOP的使用者来说,只要指定2个信息:
- 在哪里切入
- 切入的增强处理是什么?
一旦指定了这两个信息,AOP框架会帮我们完成实际的织入。
AOP
AOP作用——不要加班。
当应用程序需要进行一种“具有横切性质的”修改,
这种修改又跨多个方法,需要改动的地方很多。
一旦有了AOP框架,对于开发人员来讲,要干什么?
1. 在哪个“切面”插入增强处理。
2. 插入怎样的“增强处理”。
一旦开发人员提供了这两个信息,剩下事情交给AOP框架去完成。
Before Advice(前置增强处理)
After Advice(后置增强处理)
1. 只要目标方法结束(不管A。成功返回;B。遇到异常),都会织入。
2. 它也不能访问目标方法的返回值。
3. 它不能阻止目标方法的执行。
类似finally关键字:回收物理资源。
AfterReturning Advice(方法成功返回后的增强处理)
1. 它不能阻止目标方法的执行。
2. 它可以访问目标方法的返回值,它不能改变目标方法的返回值。
3. 只有在目标方法成功返回后,它才会织入。
AfterThrowing Advice(对异常的增强处理)
1. 它不能阻止目标方法的执行。
2. 可以访问目标方法所抛出的异常。
类似catch关键字:对未处理的异常进行修复。但异常依然会传播出去。
Around Advice(前、后增强处理)
1. 它可以阻止目标方法的执行。
2. 它可以访问目标方法的形参,甚至改变目标方法的形参。
3. 它可以访问目标方法的返回值,甚至改变目标方法的返回值。
所有增强处理都可以访问目标方法的参数。
1. 用args指示符。也可以对所匹配的目标方法的形参进行限制
2. 在增强处理方法增加一个形参:
<aop:pointcut.../>元素,用于配置一个切入点。
本质:就是给切入点表达式起个名字,方便以后复用。、
and / or / not
Spring 与前端框架的整合。
前端框架:Struts 1 / DWR / Struts 2
Struts 1
+ Spring + Hibernate
DWR
Spring 本质:你用XML配置(Annotation)驱动Java代码。
所以,Spring框架与前端框架的整合的关键:
如何将Spring容器中的Service组件,注入前端组件。
ApplicationContext 与 BeanFactory
ApplicationContext 比 BeanFactory多一些功能:
可以声明式的方式创建Spring容器。
实现思路:
1. 创建ServletContextListener
2. Web应用启动时,回调 监听器的contextInitial()方法,就可在该方法里
调用new XxxApplicationContext("dddd") → Spring 容器
接着把Spring容器放到 application (ServletContext)里。
Spring 与Struts 1整合的步骤:
(1) 复制Spring ,Struts 的JAR包。
(2) 在web.xml文件中配置加载Spring容器。 提供Spring配置文件。
(3) 在web.xml文件中配置Struts 1的核心控制器,提供struts-config.xml文件。
(4) 在struts.xml文件,增加controller元素,该元素用于替换Struts 1的
RequestProcessor
(5) 在struts.xml文件中配置action元素时,无需指定type属性。
主要让该action的path属与Spring容器中某个Bean的name属性相同即可。
Spring 与DWR整合的步骤:
(1) 复制Spring ,DWR的JAR包。
(2) 在web.xml文件中配置加载Spring容器。 提供Spring配置文件。
(3) 在web.xml文件中配置DWR的核心控制器,提供struts-config.xml文件。
(4) 在dwr.xml文件, 使用spring创建器。
Spring与Hibernate的整合
Hibernate的开发步骤:
(1) 编写POJO
(2) 映射文件。
(3) 使用Hibernate API进行持久化操作。
A。 得到Configuration
B。 得到SessionFactory
C。 得到Session
D。打开事务。
持久化操作。
E。关闭事务。
F。关闭session
G。如果应用退出,关闭sessionFactory。
Spring对Hibernate进行了简化:
1. 可以直接在配置文件配置SessionFactory,
Spring容器将负责创建 SessionFactory。
Spring容器还可以把SessionFactory注入应用组件中。
2. Spring提供了一个HibernateTemplate。
HibernateTemplate只要给它一个SessionFactory,
接下来的绝对部分crud操作只要一行代码即可。
3. Spring还提供了一个HibernateDaoSupport工具类——会作为DAO组件的基类。
该工具类主要有两个方法:
setSessionFactory() —— 可用于接受依赖注入,注入SessionFactory
getHibernateTemplate() —— 可进行持久化操作。
Spring提供了声明式的事务管理的配置
(1)配置事务管理器。
(2)使用AOP配置