Spring

1. 什么是控制反转 ? 什么是依赖注入 ?

  1. 什么是 IoC ?
    IoC 是一种叫做控制反转的编程思想,我们把对象的创建、管理的控制权都交给 Spring 容器,这是一种控制的反转,所以Spring容器才能称为IoC容器。
  2. 为什么使用 IoC ?
    复杂的应用程序类与类的协作关系往往是多边的,我们并不知道一个类功能的实现会依赖多少个另类对象来协作,所以在类中自行创建对象并且管理对象的整个生命周期,会造成代码的高度耦合以及不可想象的复杂度。如果我们能将对象的生命周期交给第三方组件来管理,当某个类需要另外的对象时第三方组件就直接创建出来交给它,这样,类就可以只专注于自己功能的实现,而不用去管理其他类对象的生命周期,这样类的功能就单纯了很多。
    Spring(容器)就是这个第三方组件。我们只需要告诉Spring(容器)有哪些对象需要管理就行了,不用去关心Spring框架是如何创建对象的。这样,当某个类A需要类B对象时,如果类B已经声明交给了Sping容器管理,那么在程序运行到类A需要类B时,Spring容器就通过依赖注入的方式,将类B对象注入到类A中协助完成业务功能。
  3. Java 中依赖注入的方式:
    (1)构造器注入
    (2)setter 方法注入
    (3)接口注入

2. Spring 的几种配置方式 ?

  1. 基于 xml 的配置
  2. 基于注解的配置
  3. 基于 Java 的配置

3. Spring Bean 的生命周期 ?

  1. 实例化 bean 对象【通过构造方法或工程方法】
  2. 设置对象属性【依赖注入】
  3. 将 Bean 实例传递给 Bean 的前置处理器的 postProcessBeforeInitialization(Object bean, String beanname) 方法
  4. 调用Bean的初始化方法
  5. 将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
  6. 使用Bean
  7. 容器关闭之前,调用Bean的销毁方法

4. Spring 框架中都用到了哪些设计模式 ?

  • 代理模式:AOP
  • 单例模式:在 spring 配置文件中定义的 bean 默认为单例模式
  • 模板方法:用来解决代码重复的问题
  • 工厂模式:BeanFactory 用来创建对象的实例

5. BeanFactory 和 ApplicationContext 有什么区别 ?

  1. BeanFactory 是 Spring 里面最底层的接口,提供了最简单的容器功能,只提供了实例化对象的取对象的功能。

  2. ApplicationContext
    应用上下文,继承了 BeanFactory 接口,它是 Spring 的一种更加高级的容器,提供了更多有用的功能。
    (1)国际化(MessageSource)
    (2)访问资源,如URL和文件(ResourceLoader)
    (3)载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
    (4)消息发送、响应机制(ApplicationEventPublisher)
    (5)AOP(拦截器)

  3. 两者装载 bean 的区别
    (1)BeanFactory:
    BeanFactory在启动的时候不会去实例化Bean,只有从容器中拿Bean的时候才会去实例化;
    (2)ApplicationContext:
    ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;

  4. 我们该用 BeanFactory 还是 ApplicationContent ?

    延迟实例化的优点:(BeanFactory)
    应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势。

    不延迟实例化的优点: (ApplicationContext)
    (1)所有的Bean在启动的时候都加载,系统运行的速度快;
    (2) 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
    (3)建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

  5. Spring事件机制(订阅发布模式 == 观察者模式)
    ApplicationContext事件机制是观察者设计模式的 实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。 如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。
    两个重要成员
    ApplicationEvent:容器事件,必须由ApplicationContext发布;
    ApplicationListener:监听器,可由容器中的任何监听器Bean担任。

6. Spring 容器创建 bean 实例的方法

  1. 通过无参构造函数的方法创建 bean 实例
  2. 通过静态工厂方法创建 bean 实例
  3. 通过实例化工厂方法创建 bean 实例

7. Spring 初始化顺序

Spring 容器载入 bean 顺序是不确定的,Spring 框架没有约定特定顺序逻辑规范。但 Spring 保证如果 A 依赖 B (如 bean A 中有@Autowired B 的变量),那么B将先于A被加载。但如果beanA不直接依赖B,我们如何让B仍先加载呢?
一个场景中,bean A是事件发布者(或JMS发布者),bean B (或一些) 负责监听这些事件,典型的如观察者模式。我们不想B 错过任何事件,那么B需要首先被初始化。
简言之,有很多场景需要bean B应该被先于bean A被初始化,从而避免各种负面影响。

  1. depends-on
    depends-on用来表示一个Bean的实例化依靠另一个Bean先实例化。即通过定义depends-on=”XXX”可以控制Sping实例化bean的顺序。
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>  
<bean id="manager" class="ManagerBean" />  
      
  1. 注解
    A 依赖 B ,如 bean A 中有@Autowired B 的变量,那么B将先于A被加载

8. Bean 的作用域

  1. bean 的范 bean scope 特性定义,如果没有指 scope 特性,则表示该 bean 是singleton 范围的
  2. 也可以设置为 prototype
  3. 准确的说,每次spring要获取bean的时候,都会调用getBean()方法。如果这个bean是singleton,那就会取唯一的一个实例出来。如果是prototype,那么每次getBean(),都会new一个新实例。
  4. Web 应用中, Spring 允许你指定其他的范围: request、session、websocket、application 和 globalSession
singletion
  1. srngleton 范围是应用程序上下 XML 件中定义的所有 bean 的默认范围。singleton 范围 bean 实例在创建 Spring 容器时创建,在 Spring 容器被销毁时销毁。Spring 器会为 singleton 范围 bean 创建唯一实例 ,该实例由依赖于它的所 bean 共享。

  2. sing eto 范围 bean 实例 的范围仅限于 Spring 容器实例。这意味着如果使用相同的配置元数据创建Spring 容器的两个实例, Spring 容器都将得到属于其自己的 singleton bean 实例集合。
    这里创建两个Spring容器:
    在这里插入图片描述
    使用两个容器以创建实例:
    在这里插入图片描述
    结论是两个实例是不同的,并不是一个实例。也就是说每个 Spring 容器会创建属于自己的 singleton 范围的 bean 实例。

  3. applicationContext.xml 中对于同一个类的多个 bean 定义:
    在这里插入图片描述
    测试:
    在这里插入图片描述
    利用同一个容器寻找多个bean定义下创建的bean,发现是不同的实例。也就是说,在 Spring 容器下,每个 bean 定义都存在一个 singleton 范围的 bean 实例。

  4. 延迟初始化一个 singleton 范围的 bean
    在这里插入图片描述
    当创建 Spring 容器时,BeanA 也被实例化,因为它没有设置延迟初始化。此外,LazyBean 将在第一次调用 getBean 方法来检索 lazyBean 的实例时被初始化。

prototype

每次从容器中调用Bean时,都返回一个新的实例。Sprototype 范围 bean 的另外一个独特之处在于他们总是被延迟加载。

9. 自动装配依赖项

Spring ,可以选择使 元素显式指定 bean 依赖项,或者让 Spring 自动解析 bean 依赖项。Spring 自动解 依赖项的过程称为“自动装配。

元素 autowire 特性指定了如何由 Spring 自动解决 bean 依赖项。 autowire 特性可以是以下任何值: dfault、 byNme、 byType constructor 和 no。现在我们来详细分析这些特性值。

  1. byType
    如果将 autowire 特性的值制定为 byType,那么 Spring 将根据其类型自动装配 bean 属性。例如,如果 bean A 定义了X类型的属性, Spring 会在 ApplicationContext 中寻找一个类型为 X 的 bean ,并将其注入 bean A。
  2. constructor
    Spring 将根据其类型自动装配 bean 类的构造函数参数。
  3. byName
    Spring 将根据名称自动选择 bean 属性。
  4. default/no
    对该 bean 禁用装配功能。

10. Spring 注释驱动开发

Spring
  1. @Component:用来标识这是一个 Spring Bean 的类
  2. @Service:标明这是一个服务类
  3. @Controller:标明这是一个控制器
  4. @Respository:标明这是一个dao
  5. @Autowired:通过类型自动装配依赖项
SpringMVC
  1. @RequestMapping:注解式映射器,对类中标记了 @RequestMapping 的方法进行映射
  2. @RequestParam:将请求参数传递给控制器方法

21. SpringMVC 的执行流程

在这里插入图片描述

  1. 处理器指的就是我们写的 Controller 。用户的请求是怎么到达正确的 Controller 的呢?
  2. 比如用户输入一个网址 hocalhost:8080/springmvc/item/itemlist.action 发送请求,这时用户的请求到达前端控制器 DispatcherServlet,前端控制器会将 /item/itemlist.action 取出来,执行请求查询Handler(Controller) ,就是将这个地址交给处理器映射器(HandlerMapping),处理器映射器会查找 Controller,返回的是包名+类名+方法名,之后将这个返回值返回给前端控制器。
  3. 找到要具体执行的方法以后,请求执行 Handler(Controller) ,这是用到处理器适配器,这个方法是由处理器适配器来执行的。处理器Handler返回一个ModelAndView给处理器适配器,然后处理器适配器将ModelView交给前端控制器。
  4. 前端控制器拿到ModelView以后将它交给视图解析器ViewResolver,视图解析器会将ModelAndView中的数据加入到jsp页面中,形成一个View对象(就是有数据也有页面的一个对象)。最后经过渲染视图,将页面返回给客户。

注解映射器和适配器

注解式映射器,对类中标记了 @RequestMapping 的方法进行映射。根据@ResquestMapping定义的url匹配 @ResquestMapping 标记的方法,匹配成功返回HandlerMethod对象给前端控制器。HandlerMethod 对象中封装url对应的方法Method。

@RequestMapping:定义请求url到处理器功能方法的映射

@RequestParam 将请求参数传递给控制器方法

SpringMVC 参数绑定

参数绑定,简单来说就是客户端发送请求,而请求中包含一些数据,那么这些数据怎么到达 Controller ?这在实际项目开发中也是用到的最多的,那么 SpringMVC 的参数绑定是怎么实现的呢?下面我们来详细的讲解。

SpringMVC 参数绑定

在 SpringMVC 中,提交请求的数据是通过方法形参来接收的。从客户端请求的 key/value 数据,经过参数绑定,将 key/value 数据绑定到 Controller 的形参上,然后在 Controller 就可以直接使用该形参。

例子

页面点击修改按钮,发起请求
http://127.0.0.1:8080/springmvc-web/itemEdit.action?id=1

需要从请求的参数中把请求的id取出来。
Id包含在Request对象中。可以从Request对象中取id。

想获得Request对象只需要在Controller方法的形参中添加一个参数即可。Springmvc框架会自动把Request对象传递给方法。

@RequestMapping("/itemEdit")
public ModelAndView queryItemById(HttpServletRequest request) {
	// 从request中获取请求参数
	String strId = request.getParameter("id");
	Integer id = Integer.valueOf(strId);

	// 根据id查询商品数据
	Item item = this.itemService.queryItemById(id);

	// 把结果传递给页面
	ModelAndView modelAndView = new ModelAndView();
	// 把商品数据放在模型中
	modelAndView.addObject("item", item);
	// 设置逻辑视图
	modelAndView.setViewName("itemEdit");

	return modelAndView;
}
默认支持的参数类型

处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。

  1. HttpServletRequest:通过request对象获取请求信息
  2. HttpServletResponse:通过response处理响应信息
  3. HttpSession:通过 session 对象得到 session 中存放的对象
  4. Model/ModelMap
    除了ModelAndView以外,还可以使用Model来向页面传递数据。如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替代。
  5. ModelMap
    ModelMap是Model接口的实现类,也可以通过ModelMap向页面传递数据。
绑定简单类型

当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。这样,从Request取参数的方法就可以进一步简化。

/**
 * 根据id查询商品,绑定简单数据类型
 * 
 * @param id
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(int id, ModelMap model) {
	// 根据id查询商品数据
	Item item = this.itemService.queryItemById(id);

	// 把商品数据放在模型中
	model.addAttribute("item", item);

	return "itemEdit";
}
支持的数据类型

参数类型推荐使用包装数据类型,因为基础数据类型不可以为null。
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean

@RequestParam

当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。但是如果不一致呢?我们使用 @RequestParam 注解来完成。

JSP页面代码不变,保持原样,Controller 代码如下:
在这里插入图片描述
使用@RequestParam常用于处理简单类型的绑定。
value:参数名字,即入参的请求参数名字,如value=“itemId”表示请求的参数 区中的名字为itemId的参数的值将传入。

required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错

defaultValue:默认值,表示如果请求中没有同名参数时的默认值

绑定 pojo 类型

请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
在这里插入图片描述

/**
 * 更新商品,绑定pojo类型
 * 
 * @param item
 * @param model
 * @return
 */
@RequestMapping("/updateItem")
public String updateItem(Item item) {
	// 调用服务更新商品
	this.itemService.updateItemById(item);

	// 返回逻辑视图
	return "success";
}

SpringMVC 拦截器

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

springmvc与struts2不同

  1. springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过滤器。
  2. springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
  3. Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面。Jsp视图解析器默认使用jstl。

Spring AOP

描述以下 Spring AOP

Spring AOP 【面向切面编程】是面向对象编程的补充。在面向对象编程中,关键单元是对象,AOP 的关键单元是切面,或者说关注点。
AOP 让你可以使用简单的可插拔的配置,在实际逻辑执行之前、之后或周围动态添加横切关注点。这让代码在当下和将来都变得易于维护。如果你是使用XML来使用切面的话,要添加或删除关注点,你不用重新编译完整的源代码,而仅仅需要修改配置文件就可以了。
Spring AOP通过以下两种方式来使用。但是最广泛使用的方式是Spring AspectJ 注解风格。

在Spring AOP中关注点和横切关注点有什么不同?

关注点是我们想在应用的模块中实现的行为。关注点可以被定义为:我们想实现以解决特定业务问题的方法。比如,在所有电子商务应用中,不同的关注点(或者模块)可能是库存管理、航运管理、用户管理等。
横切关注点是贯穿整个应用程序的关注点。像日志、安全和数据转换,它们在应用的每一个模块都是必须的,所以他们是一种横切关注点。

Spring中有哪些不同的通知类型?

通知(advice)是你在你的程序中想要应用在其他模块中的横切关注点的实现

Spring AOP 代理是什么?
  1. 代理是使用非常广泛的设计模式。简单来说,代理就是可以控制另外一个对象的对象,但它添加了一些特殊的功能。
  2. Spring AOP 是基于代理实现的。AOP 代理是一个由 AOP 框架创建的用于在运行时实现切面协议的对象。
  3. Spring AOP 默认为 AOP 代理使用标准的 JDK 动态代理。这使得任何接口可以被代理。Spring AOP 也可以使用 CGLIB。如果业务中没有实现任何接口,那么默认使用CGLIB。
实现技术

AOP 主要的实现技术有 Spring AOP 和 AspectJ。

  1. AspectJ 的底层技术
    AspectJ 的底层技术是静态代理,即用一种 AspectJ 支持的特定语言编写切面,通过一个命令来编译,生成一个新的代理类,该代理类增强了业务类,这是在编译时增强,相对于下面说的运行时增强,编译时增强性能更好。

  2. Spring AOP
    Spring AOP采用的是动态代理,在运行期间对业务方法进行增强,所以不会生成新类,对于动态代理技术,Spring AOP提供了对JDK动态代理的支持以及CGLib的支持。

    JDK 动态代理是能为接口创建动态代理实例,而不能对类创建动态代理。需要获得目标类的接口信息(应用Java反射技术),生成一个实现了代理接口的动态代理类(字节码),在通过反射机制获得动态代理类的构造函数,利用构造函数生成动态代理类的实例对象,在调用具体方法前调用 invokeHandler 方法来处理。

    CGLib 动态代理需要依赖 asm 包,把被代理对象类的 class 文件加载进来,修改其字节码生成子类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值