Spring
Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一栈式) 轻量级开源框架。
作用:解耦
主业务逻辑:功能一般在一个特定的场合使用,复用性较低
转账 借书 酒店入住
交叉业务逻辑(系统级服务):不同的主业务操作中的一些可以复用的功能
记录日志,处理事务
Sping核心
IOC:Inversion of Control: 控制反转
控制反转:解决主业务的耦合。
程序中使用的核心对象不再需要程序员new()了,Spring容器给我们创建核心对象。
对应的创建权不再是程序员了。
AOP:Aspect Oriented Programming的缩写:面向切面编程,
(Oriented adj. 面向,以……为方向的)
面向切面编程:解决主业务与交叉业务直接的耦合。
将交叉业务封装成一个切面,织入到主业务中。
相对于EJB Spring更轻量级
一栈式:Spring可以管理三层(持久层、业务层、表示层)中 每一层的核心对象、核心类。MyBatis只能管理Dao层。
使用Spinrg来开发,可以不使用其他框架就能实现三层的所有功能。
dao层:jdbc dbutil mybatis jdbctemplate(来自Spring中的一个模块)
Service层: Sping可以管理事务。(不用自己再开启 关闭事务了)
ui:servlet stu2 SpingMVC(Spring中的一个模块)
入门程序
是所有Sping框架的核心。
Sping的组成部分
搭建一个Sping框架需要的四个容器:
入门程序需要的jar包:七个包。前五个是必须的。
四个核心包:
beans.jar
core.jar
context.jar
spingexpression.jar
依赖包:
logging.jar
log4j.jar(不显示日志信息可以不加)
junit.jar
在这里找约束头
接口
实现类
在这里配bean即可,先导入源码,就是那些容sources结尾的jar包,里面都是框架提供的源码。
通过观察源码。找到我们需要的方法
这是使用类路径的。
若使用 文件系统的路径(一般不用)
导入介绍文件
另外一种 BeanFactory。
ApplicationContext(上下文、配置文件)和 BeanFactory::区别:
ApplicationContext:
容器初始化的时候。会将多有的bean创建。
优点:第一次请求响应速度快。
缺点:当配的bean比较多的时候,调用的时候都会被创建,过多的消耗和占用系统资源。
BeanFactory:
调用getBean()方法,获取对象时才会创建。
Bean的装配 (创建)
容器如何创建bean对象?
1.创建对象,一定要提供无参构造
创建bean对象底层使用的是反射,一般都是使用无参构造器。
2.配置xml文件。
3.创建对象。实现功能
动态工厂bean
创建一个工厂,工厂返回一个产品。
但是这个工厂模式:测试类和工厂有耦合。
换一个工厂,就要重新new一个工厂
解决:使用spring 让工厂用容器来创建。
(注意:图上这个path的路径,是由于xml文件被放在了ba02包内。使用classpath的时候只需要写xml文件名即可。
使用fileClassPath的时候才需要写完整路径。)
但是若工厂里面有很多产品的时候,还是会有耦合。
这种方法
并没有真正的解耦。
原因是将工厂bean当成了一个普通的javabean来使用,用了框架,不但没有解耦,反而更复杂了。
没有用Spring 的动态工厂bean
解决:真正的动态工厂:配置如下!
这个时候,尽管工厂里面有很多方法,在配置文件里面写这个方法即可,不会初始化其他方法。
(不生成工厂bean 而是生成普通的bean,然后给普通的bean配置工厂属性。注意一定要有工厂bean)
静态工厂bean
声明工厂的时候不变,但是工厂方法是静态方法,不需要配置工厂bean , 直接写好配置 方法名就可以直接调用。
bean的作用域
单例设计模式:
发现两个相等,
原型设计模式:
发现两个获取的bean不相等
Bean后处理器
AOP(面向切面编程)的底层实现和他有关
AOP就是增强:底层使用动态代理或者cglib
Bean后处理器是一个特殊的bean,
自定义一个类,去实现bean后处理器的接口,然后在容器中去配置该类的一个bean。就获得了bean后处理器。
为什么特殊呢?
因为在容器中配的这个bean 不需要id,容器中的bean对象在创建时都会自动执行bean后处理器中的两个方法。
Post Processor(后置处理程序)
这两个方法 有两个参数 bean 、 beanName
bean:当前容器初始化的bean对象
beanName:当前bean对象的name
beanName 就是这个id
====
Bean后处理器可以增强这个类中方法的功能。
如果没有判断,就会增强每个类的方法
proxy:代理
proxyInstance:代理实例
invocation :调用
Handler:处理程序
invoke:调用
若只想增强某一个类的某一个方法,另外的方法不增强、
现在就只增强了doSome了
====
设置只增强do开头的方法
====
设置只增强某个类,其他的类不增强。
目前一个接口,两个实现类。
如果没有设置,两个类都会增强。
这个里面的proxy 就是动态代理
里面加一句增强功能
在增强里面主业务前加了某些业务,这就是织入。
定制Bean 的生命周期的始末。
配置
这里发现不显示tearDown.(没有显示teardown里面的方法,即输出那句话)
因为必须需要手动关闭。
在关闭的时候使用ac调用方法,发现没有close方法, 这是由于多态,不能访问子类特有的方法。(new的是一个Service,但是tearDown的方法在子类ServiceImpl里面)不能直接调用销毁方法,因为权限不够。
需要向下转型。
====
Bean的生命周期
Spring框架中Bean的生命周期比较复杂。一共有11个阶段。
第一阶段:创建对象,先写一个构造器。
写配置文件:这里先测试一下,能否获得这个bean的name,能否使用getName方法
发现可以获得这个实体bean的name属性。
第二阶段:属性赋值
第三阶段:实现BeanNameAware接口
第四阶段:实现BeanFactoryAware接口
第五阶段:进入Bean后处理器。
第六阶段:InitializingBean,bean属性值设置
、
第七阶段:
第八阶段:
第九阶段:
第十阶段:
第十一阶段:
测试:生命周期的11个阶段:注意:这里的bean后处理器里面不能写加强方法(不能使用动态代理)
JDK动态代理和cglib
JDK动态代理:
被增强的类必须有接口
动态代理增强的是接口的实现类对象,和实现类是平级的。
cglib:
目标类有没有接口都可以增强
代理对象是目标类的子类对象。
Spring框架底层使用AOP增强,如果有接口就使用Proxy,没有接口就选择cglib.
若打印出来的类 以美元$开头,那么一定是通过Proxy增强的。同样的cglib增强的前缀会有cglib