概述:Spring是轻量级的开源的JavaEE框架
spring框架的主要特点:
在Spring的工作方式中,所有的类都会在spring容器中登记,告诉spring这是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。
所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
IOC底层原理
xml解析、工厂模式、反射
IOC的过程:
1、第一步 配置XML文件,配置创建的对象。
<bean id=”dao” class = “com.hwl.UserDao”>bean>
2、第二步 有service类和dao类,创建工厂类
class UserFactory{
public static UserDao getDao(){
String classValue = class属性值; //xml解析
//通过反射创建对象
Class classz = Class.forName(classVlue);
return (UserDao)classz.newInstance();
}
}
IOC的本质:就是基于IOC容器完成,IOC容器底层就是对象工厂。
IOC接口(BeanFactory)
IOC操作(基于xml)
IOC操作(基于注解)
概念:面向切面编程。意为:在不修改源代码的情况,进行功能的增强。
面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
通俗的描述:不通过修改源码的方式,在主干功能里面添加新的功能。
使用登录的例子说明AOP
例如:现在有一个登录功能,用户输入账号面就可以登录,但是该用户是一个新用户,如果现在需要添加一个注册功能,按照之前的逻辑,就需要在,源代码的上面去进行功能的添加,同时代码量也会增加,但是如果利用aop的思想,我们就可以在登录方法前或者后,添加注册功能,同时两个模块互不干扰,从而也可以降低耦合度。
实现AOP的两种方法:
简单来说,Spring容器是用来装Spring Bean的。
在Spring中,所有的java对象均交由Spring容器使用DI(dependency injection)来进行托管,在需要时进行调用,并维护其生命周期。
所以,我们看到Spring容器和Spring bean是一种包含的关系,容器装载并维护着bean。
Spring中的容器是不唯一的,但大体上包括两个:BeanFactory和ApplicationContext
这两者都能,加载配置文件,通过工厂的这个过程,去创建对象
1、BeanFactory:
2、ApplicationContext:
两者之间的区别:
id : bean的唯一标志
class :bean的类型
factory-method :调用工厂方法,创建对象
factory-bean :调用创建对象的bean , 然后再factory-method 设置需要调用的具体的方法。
scope:
<bean id="test" class="com.hqyj.entity.Phone" scope="prototype">bean>
<bean id="test1" class="com.hqyj.entity.Phone" scope="singleton">bean>
<bean id="example" class="com.hqyj.entity.ExampleBean" init-method="init" scope="prototype" destroy-method="destroy">bean>
beans>
autowire:自动装配, 为了减少构造器函数初始化对象和set注入初始化对象, 可以使用autowire ,
让spring框架的容器对象,自动匹配容器中的其他bean对象,然后给bean进行初始化。
**autowire: 自动装配, 根据spring容器中的对象的id 或对象的类型 ,按照自动装配的规 则,给对象的属性初始化。
** constructor :按构造器函数进行匹配
** byType : set注入 ,调用无参构造函数,然后根据容器中的对象的类型和类的 属性的类型, 调用set方法 ,如果有多个符号条件的类型,则抛出异常
** byName : set注入 ,调用无参构造函数,然后根据容器中的对象的id和类的 属性的属性名 , 调用set方法, 如果id匹配成功,但是类型不正确,则抛出异 常。
** byType , byName使用的时候,对于容器中的jdk提供的类型不能自动装配
@Autowired :
当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor
将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired
注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。
@Qualifier:
我们在 Spring 容器中配置了两个类型为 相同类型的 Bean,当对 Boss 的 office
成员变量进行自动注入时,Spring 容器将无法确定到底要用哪一个 Bean,因此异常发生了。
<bean id="office" class="com.baobaotao.Office">
<property name="officeNo" value="001"/>
bean>
<bean id="office2" class="com.baobaotao.Office">
<property name="officeNo" value="001"/>
bean>
Spring 允许我们通过 @Qualifier
注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:
@Autowired
public void setOffice(@Qualifier("office")Office office) {
this.office = office;
}
@Autowired和@Qualifier:
@Autowired
可以对成员变量、方法以及构造函数进行注释@Qualifier
的标注对象是成员变量、方法入参、构造函数入参。@Autowired
和@Qualifier
统一成一个注释类。public class Boss {
@Autowired
private Car car;
@Autowired
@Qualifier("office")
private Office office;
@Resource:
@Resource
的作用相当于 @Autowired
,只不过 @Autowired
按 byType 自动注入,@Resource
默认按 byName 自动注入罢了。@Resource
有两个属性是比较重要的,分别是 name 和 type。@Resource
注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。import javax.annotation.Resource;
public class Boss {
// 自动注入类型为 Car 的 Bean
@Resource
private Car car;
// 自动注入 bean 名称为 office 的 Bean
@Resource(name = "office")
private Office office;
}
@PostConstruct 和 @PreDestroy
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作。
您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 < bean > 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法。
初始化之后和销毁之前指定定义了两个注释类,分别是@PostConstruct 和 @PreDestroy
这两个注释只能应用于方法之上。
@PostConstruct 注释的方法将在类实例化后调用。
@PreDestroy 的方法将在类销毁之前调用。
import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Boss {
//使用byTyoe
@Resource
private Car car;
//使用byName的方式进行注入
@Resource(name = "office")
private Office office;
//方法将在类实例化后调用.
@PostConstruct
public void postConstruct1(){
System.out.println("postConstruct1");
}
//方法将在类销毁之前调用.
@PreDestroy
public void preDestroy1(){
System.out.println("preDestroy1");
}
…
}
问题:解释一下spring bean的生命周期?
(1)实例化Bean:
- 对于BeanFactory容器,当客户向容器请求一个尚未初始化的Bean时,或者初始化Bean的时候,需要注入另一个尚未初始化的依赖的时候,容器就会调用creatBean进行实例化。
- 对于ApplicationContext容器,当容器启动结束之后,通过获得BeanDefiniton对象中的信息,实例化所有的Bean。
并设置对象属性(依赖注入)
首先实例化后的对象被封装在BeanWrapper(wrapper:包装)对象中,紧接着,Spring根据BeanDefifinition(Defifinition:定义,释义)中的信息 以及 通 过BeanWrapper提供的设置属性的接口完成依赖注入。
处理Aware接口:
接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方
法,此处传递的就是Spring配置文件中Bean的id值;
②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的
是Spring工厂自身。
③如果这个Bean已经实现了ApplicationContextAware接口,会调用
setApplicationContext(ApplicationContext)方法,传入Spring上下文;
(2)InitializingBean 与 init-method:
如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
(3)运行使用对象
(4)销毁
DisposableBean:
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的
destroy()方法;
destroy-method:
最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
问题2:解释Spring支持的几种bean的作用域。
Spring容器中的bean可以分为5个范围:
(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回
收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean
会随之失效。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器
中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局
变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
1、首先MVC是一种设计模式。
2、M:Model 模型(完成业务逻辑)
3、V:View 视图(前端页面展示数据)
4、C:Controller 控制器(接收请求—>调用Model (模型)—>发送响应结果)
1、springMVC是一个MVC的开源框架
2、springMVC是spring的一个后续产品,其实就是spring在原有基础上,又提供了web应用的MVC模块,可以简单的把springMVC理解为是spring的一个模块
3、springMVC就是spring的一个子模块,所以根本不需要和spring进行整合。
第一步: 用户发起请求到前端控制器(DispatcherServlet)
第二步: 前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
第三步: 找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
第四步: 前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
第五步: 处理器适配器去执行Handler
第六步: Handler执行完给处理器适配器返回ModelAndView
第七步: 处理器适配器向前端控制器返回ModelAndView
第八步: 前端控制器请求视图解析器(ViewResolver)去进行视图解析
第九步: 视图解析器像前端控制器返回View
第十步: 前端控制器对视图进行渲染
第十一步:前端控制器向用户响应结果
有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。
Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句
本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原
生态sql,可以严格控制sql执行性能,灵活度高。
优点:
XML里,便于统一管理。
提供XML标签,支持编写动态SQL语句,并可重用。
与JDBC相比,减少了很多重复的代码,而且不需要手动开关连接;
很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库
MyBatis都支持)。
缺点:
要求。
需要注意的地方:使用#{}可以防止SQL注入,提高安全性。
1、用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件)。
2、创建独立的spring引用程序 main方法运行。
3、内部嵌入的服务器,无需部署war文件。
4、简化maven配置。
需要注意的地方:使用#{}可以防止SQL注入,提高安全性。
1、用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件)。
2、创建独立的spring引用程序 main方法运行。
3、内部嵌入的服务器,无需部署war文件。
4、简化maven配置。
以上就是个人在框架阶段所总结的一些,经常运用频繁的知识点,和一些容易混淆的知识点。
其实在学习框架这个阶段,自己也在不断地融会贯通前面的知识,当自己所学的知识,都能用自己的想法、表述或者代码去实现的出来的时候,自己也才算是理解的时候。
当然,在这期间,自己也学习到了很多优秀的编程思想。自己也学会了去试探性的尝试,尝试去接触那未知的技术。