Spring知识点总结(持续更新中---)

Spring的优点

  • 轻量,基本版本大约2MB。
  • 通过控制反转和依赖注入实现松耦合。
  • 支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
  • 通过切面和模板减少样板式代码。
  • 方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hibernate、MyBatis等)。
  • 方便程序的测试。Spring支持Junit4,添加注解便可以测试Spring程序。

一、IOC

1、什么是Spring IOC容器?

控制反转(也称作依赖性介入-Inversion Of Controller)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器 (在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。
简单说spring不用开发者实例化对象,自己实例化对象,开发者直接使用即可,同时也不需要开发者,管理对象,spring帮助我们管理对象,它主要是通过将类在配置文件中描述(applicationContext.xml)该描述文件称为容器文件,程序只要读取容器文件的bean,其实就是类,获得对象即可。
spring实例对象的原理是:使用单例模式和原型模式进行对象的实例化。
SpringIoc

2、IOC3种注入方式

1、构造函数注入
2、setter注入
3、接口注入 - 应该叫做:注解注入

  • 构造函数注入
    我们先声明一个有参的构造函数,无需生成get,set方法。
public class Student {
	private int id;
	private String name;
	public Student(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}
}

在Spring配置文件applicationContext.xml中,声明bean定义

<bean class="sjc.beans.Student">
	<property name="id" value="0001"></property>
	<property name="name" value="zhangsan"></property>
</bean>

在声明ApplicationContext的依赖查找getBean方法

public static void main(String[] args) throws Exception{
	ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
	Student zhangsan = ac.getBean(Student.class);
	System.out.println(zhangsan.toString());
}
控制台输出
Student [id=1, name=张三]
  • Setter注入
    将Student类的有参构造函数去掉,加入set,get方法。
public class Student {
	private int id;
	private String name;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}
}

将spring配置文件改为:。property 对应为属性。

<bean class="sjc.beans.Student">
	<property name="id" value="0001"></property>
	<property name="name" value="zhangsan"></property>
</bean>

控制台输出
Student [id=1, name=张三]
  • 接口注入
    我们先创建一个Teacher类。将Student类中,加入属性Teacher,并使用@Autowired注解。
public class Teacher {
	private int id;
	private String name;
}

public class Student {
	private int id;
	private String name;
	@Autowired
	private Teacher teacher;
	
    get set toString方法省略.....
}

配置文件修改为:

<bean class="sjc.beans.Student"></bean>
<bean class="sjc.beans.Teacher"></bean>

运行上面的main方法中的getBean,控制台输出
Student [id=0, name=null, teacher=Teacher [id=0, name=null]]

这里teacher不为null,说明teancher注入成功。

总结一下:
1、Spring可以通过配置文件或者注解描述类与类之间的依赖关系,自动完成类的初始化和依赖注入工作。
2、比如,xml配置文件,通过new XmlBeanFactory(“beans.xml”)等方式即可启动容器。在容器启动时,Spring根据配置文件,自动实例化bean并完成依赖关系的装配,从容器中即可返回装备就绪的Bean实例。这里使用的是Java的反射机制

二、Bean

1、bean定义

在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。

  • 我们总结如下:
    1.bean是对象,一个或者多个不限定
    2.bean由Spring中一个叫IoC的东西管理
    3.我们的应用程序由一个个bean构成

2、Bean的作用域在这里插入图片描述

3、bean生命周期

Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象;使用Singleton模式产生单一实例,在spring中,singleton属性默认是true,只有设定为false,则每次指定别名取得的Bean时都会产生一个新的实例,Spring只帮我们管理单例模式Bean的完整生命周期,对于prototype的bean,Spring在创建好交给使用者之后则不会再管理后续的生命周期。

Bean的生命周期概括起来有四个阶段:
实例化 -> 属性赋值 -> 初始化 -> 销毁

  • spring在调用bean的时候因为作用域的不同,不同的bean初始化和创建的时间也不相同。 在作用域为singleton的时候,bean是随着容器一起被创建好并且实例化的, 在作用域为pritotype的时候,bean是随着它被调用的时候才创建和实例化完成。 然后程序就可以使用bean了,当程序完成销毁的时候,bean也被销毁。
    在这里插入图片描述
  • 1、实例化
    实例化一个Bean,即new。
  • 2、IOC依赖注入
    按照Spring上下文对实例化的Bean进行配置。
  • 3、setBeanName实现
    如果这个Bean已经实现了BeanNameAware接口,就会调用它实现的setBeanName(String)方法,此处传递的是Spring配置文件中Bean的id值。
  • 4、setBeanFactory实现
    如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(BeanFactory)方法,传递的是Spring工厂自身。
  • 5、setApplicationContext实现
    如果这个Bean实现了ApplicationContextAware接口,会调用它实现的setApplicationContext(ApplicationContext)方法,传递的是Spring的上下文。
  • 6、postProcessBeforeInitialization实现-初始化预处理
    如果这个Bean实现了BeanPostProcessor接口,将会调用它实现的postProcessBeforeInitialization(Object obj,String s)方法。BeanPostProcessor被用作Bean内容修改,并且由于这个是在Bean初始化结束的时候调用的这个方法,也可以被用于内存或缓存技术。
  • 7、init-method
    如果这个bean在Spring配置文件中配置了init-method属性,会自动调用其配置的初始化方法。
  • 8、postProcessAfterInitialization
    如果这个Bean实现了BeanPostProcessor接口,将会调用它实现的postProcessAfterInitialization(Object obj,String s)方法。
    以上工作完成以后就可以应用这个Bean了。
  • 9、Destory过期自动清理
    当Bean不再需要时,如果这个Bean实现了DisposableBean这个接口,会调用其实现的.destory()方法。
  • 10、destory-method
    如果这个bean在Spring配置文件中配置了destory-method属性,会自动调用其配置的销毁方法。

4、初始化和销毁方法的时机?

你有没有想过这样一个问题,初始化方法和销毁方法是在什么时候被调用的啊?
1、bean对象的初始化方法调用的时机:对象创建完成,如果对象中存在一些属性,并且这些属性也都赋好值之后,那么就会调用bean的初始化方法。

单实例与多实例:Spring中Bean的单实例和多实例

  • 对于单实例bean来说,在Spring容器创建完成后,Spring容器会自动调用bean的初始化方法;
  • 对于多实例bean来说,在每次获取bean对象的时候,调用bean的初始化方法。

2、bean对象的销毁方法调用的时机:

  • 对于单实例bean来说,在容器关闭的时候,会调用bean的销毁方法;
  • 对于多实例bean来说,Spring容器不会管理这个bean,也就不会自动调用这个bean的销毁方法了。

多实例bean的生命周期不归Spring容器来管理,这里的DisposableBean接口中的方法是由Spring容器来调用的,所以如果一个多实例bean实现了DisposableBean接口是没有啥意义的,因为相应的方法根本不会被调用,当然了,在XML配置文件中指定了destroy方法,也是没有任何意义的。所以,在多实例bean情况下,Spring是不会自动调用bean的销毁方法的

5、bean之间的关系?

1、依赖
在这里插入图片描述
2、继承
在这里插入图片描述
3、集合
在这里插入图片描述

6、Bean注入容器有哪些方式?

将普通类交给Spring容器管理,通常有以下方法:
1、使用@Configuration与@Bean注解
2、使用@Controller、@Service、@Repository、@Component 注解标注该类,然后启用@ComponentScan自动扫描
3、使用@Import 方法。使用@Import注解把bean导入到当前容器中,代码如下:

//@SpringBootApplication
@ComponentScan
/*把用到的资源导入到当前容器中*/
@Import({Dog.class, Cat.class})
public class App {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
        System.out.println(context.getBean(Dog.class));
        System.out.println(context.getBean(Cat.class));
        context.close();
    }
}

7、BeanFactory和FactoryBean的区别

一个是Factory,也就是IOC容器或者对象工厂。一个是Bean,在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能产生或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。用户使用容器时,可以使用转义符“&”来得到FactoryBean本身,用来区分获取FactoryBean产生的对象和获取FactoryBean本身。

8、BeanFactory与ApplicationContext区别

Bean工厂(BeanFactory)是Spring框架最核心的接口,它提供了高级IOC的配置机制。BeanFoctory使管理不同的java对象成为可能,应用上下文(ApplicationContext)建立在BeanFactory基础上,提供了更多面向应用的功能。

称BeanFactory为IOC容器,ApplicationContext为Spring容器。简单划分:BeanFactory是Spring框架的基础设施,面向Spring本身。而ApplicationContext面向使用Spring框架的开发者,几乎所有应用场合都可以直接使用ApplicationContext,而不是BeanFactory。

9、Spring自动装配的方式有哪些?

  • Spring的自动装配有三种模式:byType(根据类型),byName(根据名称)、constructor(根据构造函数)。

byType

找到与依赖类型相同的bean注入到另外的bean中,这个过程需要借助setter注入来完成,因此必须存在set方法,否则注入失败。

当xml文件中存在多个相同类型名称不同的实例Bean时,Spring容器依赖注入仍然会失败,因为存在多种适合的选项,Spring容器无法知道该注入那种,此时我们需要为Spring容器提供帮助,指定注入那个Bean实例。可以通过<bean>标签的autowire-candidate设置为false来过滤那些不需要注入的实例Bean

<bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<!-- autowire-candidate="false" 过滤该类型 -->
<bean id="userDao2" autowire-candidate="false" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<!-- byType 根据类型自动装配userDao-->
<bean id="userService" autowire="byType" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

byName

将属性名与bean名称进行匹配,如果找到则注入依赖bean。

<bean id="userDao"  class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
<bean id="userDao2" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<!-- byName 根据名称自动装配,找到UserServiceImpl名为 userDao属性并注入-->
<bean id="userService" autowire="byName" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

constructor

存在单个实例则优先按类型进行参数匹配(无论名称是否匹配),当存在多个类型相同实例时,按名称优先匹配,如果没有找到对应名称,则注入失败,此时可以使用autowire-candidate=”false” 过滤来解决。

<!--只存在userDao2,userDao3 无法成功注入-->
<bean id="userDao2" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<bean id="userDao3" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<bean id="userService" autowire="constructor" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

@Autowired 可以传递了一个required=false的属性,false指明当userDao实例存在就注入不存就忽略,如果为true,就必须注入,若userDao实例不存在,就抛出异常。由于默认情况下@Autowired是按类型匹配的(byType),如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合。

public class UserServiceImpl implements UserService {
    //标注成员变量
    @Autowired
    @Qualifier("userDao1")
    private UserDao userDao;   
 }

byName模式 xml 配置:

<!-- 根据@Qualifier("userDao1")自动识别 -->
<bean id="userDao1" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
<bean id="userDao2" class="com.zejian.spring.springIoc.dao.impl.UserDaoImpl" />
 
<bean id="userService" class="com.zejian.spring.springIoc.service.impl.UserServiceImpl" />

@Resource,默认按 byName模式自动注入。@Resource有两个中重要的属性:name和type。Spring容器对于@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。因此使用name属性,则按byName模式的自动注入策略,如果使用type属性则按 byType模式自动注入策略。倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式注入。

@Resource(name=“userDao”)
private UserDao  userDao;//用于成员变量
 
//也可以用于set方法标注
@Resource(name=“userDao”)
public void setUserDao(UserDao userDao) {
   this.userDao= userDao;
}

上述两种自动装配的依赖注入并不适合简单值类型,如int、boolean、long、String以及Enum等,对于这些类型,Spring容器也提供了@Value注入的方式。@Value接收一个String的值,该值指定了将要被注入到内置的java类型属性值,Spring 容器会做好类型转换。一般情况下@Value会与properties文件结合使用。

jdbc.properties文件如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=root

利用注解@Value获取jdbc.url和jdbc.username的值,实现如下:

public class UserServiceImpl implements UserService {
    //占位符方式
    @Value("${jdbc.url}")
    private String url;
    //SpEL表达方式,其中代表xml配置文件中的id值configProperties
    @Value("#{configProperties['jdbc.username']}")
    private String userName;
}

xml配置文件:

<!--基于占位符方式 配置单个properties -->
<!--<context:property-placeholder location="conf/jdbc.properties"/>-->
<!--基于占位符方式 配置多个properties -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
    <property name="location" value="conf/jdbc.properties"/>
</bean>
 
<!--基于SpEL表达式 配置多个properties id值为configProperties 提供java代码中使用 -->
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <list>
            <value>classpath:/conf/jdbc.properties</value>
        </list>
    </property>
</bean>

10、@Autowired和@Resource的区别?

  • @Autowired注解可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作,它是按照类型(byType)装配依赖对象的,但是存在多个类型⼀致的bean,⽆法通过byType注⼊时,就会再使⽤byName来注⼊,如果还是⽆法判断注⼊哪个bean则会报:UnsatisfiedDependencyException。
  • @Resource会⾸先按照byName来装配,如果找不到bean,会⾃动byType再找⼀次。

11、@Bean和@Component有什么区别?

都是使用注解定义 Bean。@Bean 是使用 Java 代码装配 Bean,@Component 是自动装配 Bean。

@Component 注解用在类上,表明一个类会作为组件类,并告知Spring要为这个类创建bean,每个类对应一个 Bean。

@Bean 注解用在方法上,表示这个方***返回一个 Bean。@Bean 需要在配置类中使用,即类上需要加上@Configuration注解。

@Component
public class Student {
    private String name = "lkm";
 
    public String getName() {
        return name;
    }
}
 
@Configuration
public class WebSocketConfig {
    @Bean
    public Student student(){
        return new Student();
    }
}

@Bean 注解更加灵活。当需要将第三方类装配到 Spring 容器中,因为没办法源代码上添加@Component注解,只能使用@Bean 注解的方式,当然也可以使用 xml 的方式。

12、Spring 的单例 Bean 是否有线程安全问题?

当多个用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑,如果业务逻辑有对单例状态的修改(体现为此单例的成员属性),则必须考虑线程安全问题。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,那么不会有线程安全问题;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

  • 无状态bean和有状态bean
    有实例变量的bean,可以保存数据,是非线程安全的。
    没有实例变量的对象。不能保存数据,是线程安全的。

在Spring中无状态的Bean适合用单例模式,这样可以共享实例提高性能。有状态的Bean在多线程环境下不安全,一般用Prototype模式或者使用ThreadLocal解决线程安全问题。

三、SpringMVC

1、什么是Spring的MVC框架?

Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
Spring Web MVC也是服务到工作者模式的实现,但可进行优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

2、SpringMVC工作流程

在这里插入图片描述

3、Spring MVC框架?

在这里插入图片描述
核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、 DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

4、Spring Web MVC配置环境构建

第一步:maven构建环境配置
<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.16.RELEASE</version>
		</dependency>
第二步:在WEB-INF目录下新建springmvc.xml配置文件,同时将如下代码拷贝到文件中.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
<!-- 配置工程中那个包底下的类是控制器类 -->
	<context:component-scan base-package="com.xasxt.web" />
	<mvc:annotation-driven>
		<mvc:message-converters register-defaults="true">
			<bean class="org.springframework.http.converter.StringHttpMessageConverter">
				<constructor-arg value="UTF-8" />
			</bean>
		</mvc:message-converters>
	</mvc:annotation-driven>

</beans>
第三步:在web.xml中配置监听器及springMVC的中央控制器,代码如下
<servlet>
		<servlet-name>dispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/springmvc.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
到此springmvc开发环境构建完毕

5、Spring Web MVC常用注解标签

@Controller:用于标识是处理器类;
@RestController:用于标识是处理器类 ——> 相当于@ResponseBody + @Controller
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径 ;
@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象;
@ResponseBody:请求的body体的绑定(注解实现将conreoller方法返回对象转化为json对象响应给客户)。

6、 @Controller注解的作用

在Spring MVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在Spring MVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。

@Controller 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:

  • 在Spring MVC 的配置文件中定义MyController 的bean 对象。 在Spring MVC 的配置文件中告诉Spring
  • 该到哪里去找标记为@Controller 的Controller 控制器。

7、@ResponseBody注解的作用

  • 作用:
    该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
  • 使用时机:
    返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

8、 @PathVariable和@RequestParam的区别?

@PathVariable
1、@PathVariable用于接收uri地址传过来的参数,Url中可以通过一个或多个{Xxx}占位符映射,通过@PathVariable可以绑定占位符参数到方法参数中,在RestFul接口风格中经常使用。
2、例如:请求URL:http://localhost/user/21/张三/query
(Long类型可以根据需求改变为String或int,SpringMVC会自动做转换)

@RequestMapping("/user/{userId}/{userName}/query")
public User query(@PathVariable("userId") Long userId, @PathVariable("userName") String userName){

}

@RequestParam
@RequestParam用于将请求参数映射到控制器方法的形参上,有如下三个属性

  • value:参数名。
  • required:是否必需,默认为true,表示请求参数中必须包含该参数,如果不包含抛出异常。
  • defaultValue:默认参数值,如果设置了该值自动将required设置为false,如果参数中没有包含该参数则使用默认值。
    示例:@RequestParam(value = “pageNum”, required = false, defaultValue = “1”)

四、Spring 用到了哪些设计模式?

知识点:Java设计模式中的几种常用设计模式总结

1、简单工厂模式:BeanFactory就是简单工厂模式的体现,根据传入一个唯一标识来获得 Bean 对象。

复制代码:

<a href="/profile/992988" data-card-uid="992988" class="" target="_blank" from-niu="default" data-card-index="13">@Override
public Object getBean(String name) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name);
}</a>

2、工厂方法模式:FactoryBean就是典型的工厂方法模式。spring在使用getBean()调用获得该bean时,会自动调用该bean的getObject()方法。每个 Bean 都会对应一个 FactoryBean,如 SqlSessionFactory 对应 SqlSessionFactoryBean。

3、单例模式:一个类仅有一个实例,提供一个访问它的全局访问点。Spring 创建 Bean 实例默认是单例的。

4、适配器模式:SpringMVC中的适配器HandlerAdatper。由于应用会有多个Controller实现,如果需要直接调用Controller方法,那么需要先判断是由哪一个Controller处理请求,然后调用相应的方法。当增加新的 Controller,需要修改原来的逻辑,违反了开闭原则(对修改关闭,对扩展开放)。

为此,Spring提供了一个适配器接口,每一种 Controller 对应一种 HandlerAdapter 实现类,当请求过来,SpringMVC会调用getHandler()获取相应的Controller,然后获取该Controller对应的 HandlerAdapter,最后调用HandlerAdapter的handle()方法处理请求,实际上调用的是Controller的handleRequest()。每次添加新的 Controller 时,只需要增加一个适配器类就可以,无需修改原有的逻辑。

常用的处理器适配器:
SimpleControllerHandlerAdapter,HttpRequestHandlerAdapter,AnnotationMethodHandlerAdapter。

复制代码:

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
 
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
 
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
public class HttpRequestHandlerAdapter implements HandlerAdapter {
 
    <a href="/profile/992988" data-card-uid="992988" class="" target="_blank" from-niu="default" data-card-index="14">@Override
    public boolean supports(Object handler) {//handler是被适配的对象,这里使用的是对象的适配器模式
        return (handler instanceof HttpRequestHandler);
    }
 
    </a><a href="/profile/992988" data-card-uid="992988" class="" target="_blank" from-niu="default" data-card-index="15">@Override
    </a><a href="/profile/187852900" data-card-uid="187852900" class="" target="_blank" from-niu="default" data-card-index="16">@Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }
}</a>

5、代理模式:spring 的 aop 使用了动态代理,有两种方式JdkDynamicAopProxy和Cglib2AopProxy。

6、观察者模式:spring 中 observer 模式常用的地方是 listener 的实现,如ApplicationListener。

7、模板模式: Spring 中 jdbcTemplate、hibernateTemplate 等,就使用到了模板模式。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值