国家电力安全网站两学一做,php mysql购物网站开发,设计师家园官网,金湖网站设计文章目录 Spring面试Spring框架用了什么设计模式#xff1f;Spring Bean的作用域Spring如何解决循环依赖什么样的循环依赖无法处理构造方法注入 VS setter注入 Spring框架中有哪些不同类型的事件#xff1f;AOP (Aspect Oriented Program) 切面编程IOC容器BeanFactory 与 App… 文章目录 Spring面试Spring框架用了什么设计模式Spring Bean的作用域Spring如何解决循环依赖什么样的循环依赖无法处理构造方法注入 VS setter注入 Spring框架中有哪些不同类型的事件AOP (Aspect Oriented Program) 切面编程IOC容器BeanFactory 与 ApplicationContext 有什么区别Spring Bean的生命周期 SpringMVC原理启动流程执行流程Spring常用注解SpringMVC设置*重定向*和*转发*SpringMVC的拦截器 SpringBootSpringCloudSpringMVC设置*重定向*和*转发*SpringMVC的拦截器 SpringBootSpringCloud Spring面试
Spring框架
为了降低Java开发的复杂性Spring采取了以下4种关键策略
基于POJO的轻量级和最小侵入性编程通过依赖注入和面向接口实现松耦合基于切面和惯例进行声明式编程通过切面和模板减少样板式代码
用了什么设计模式
工厂模式 BeanFactory就是简单工厂模式的体现用来创建对象的实例单例模式 Bean默认为单例代理模式 Spring的AOP功能用到了JDK的动态代理和CGLIB的字节码生成技术模板方法 用来解决代码重复问题。比如RestTemplateJmsTemplateJpaTemplate观察者模式 定义对象建一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都会得到通过被制动更新如Spring种Listern实现的ApplicationListener
Spring Bean的作用域
singleton 默认作用域范围确保不管接收到多少个请求每个容器中只有一个bean的实例单例的模式由bean factory自身来维护 prototype 原型范围与单例范围相反为每一个bean请求提供一个实例 request 在请求bean范围内会为每一个来自客户端的网络请求创建一个实例在session过期后bean会随之失效 session 与请求范围类似确保每个session中有一个bean的实例在session过期后bean会随之失效与request区别request生命周期从HTTP请求发起开始到请求处理结束结束。而session生命周期通常与用户的会话生命周期相同从用户打开浏览器访问网站开始到用户关闭浏览器结束
Spring如何解决循环依赖
首先从一级缓存 singletonObjects中获取如果获取不到并且对象正在创建中就再从二级缓存 earlySingletonObjects中获取如果获取不到且允许singletonFactories通过getObject()获取就从三级缓存 singleFactory.getObject() 获取如果从三级缓存中获取到就从singletonFactories中移除并放入earlySingletonObjects中。也就是从三级缓存移动到二级缓存 Spring解决循环依赖的诀窍就在于三级缓存 singletonFactories它是个接口该接口在doCreateBean方法中调用了实例化步骤即在createBeanInstance之后调用也就是说单例对象此时已经被创建出来调用了构造器。虽然还不完美还没有进行后续步骤但是已经能被认出来了所以Spring将这个对象提前曝光出来让大家使用
什么样的循环依赖无法处理
因为加入singletonFactories 三级缓存的前提是执行了构造器来创建半成品对象所以构造器的循环依赖无法解决。因此Spring不能解决A的构造方法中依赖了B的实例对象同时B的构造方法中依赖了A 的实例对象这类问题Spring不支持原型(prototype)Bean属性注入循环依赖不同于构造器注入循环依赖会在创建Spring容器Context时报错它会在用户执行代码如context.getBean() 时抛出异常因为对于原型BeanSpring容器只有在需要时才会实例化、初始化它。因为Spring容器不缓存prototype类型的Bean使得无法提前暴露出一个创建中的Bean。Spring 容器在获取prototype类型的Bean时如果因为环的存在检测到当前线程已经正在处理该Bean时就会抛出异常public abstract class AbstractBeanFactoy {private final ThreadLocalObject prototypesCurrentlyInCreation new NamedThreadLocal();protected boolean isPrototypeCurrentlyInCreation(String beanName) {Object curVal this.prototypesCurrentlyInCreation.get();return (curVal ! null (curVal.equals(beanName) || (curVal instanceof Set ((Set?)curVal).contains(beanName))));}
}构造方法注入 VS setter注入
setter注入不会重写构造方法的值。如果对同一个变量同时使用了构造方法注入和setter注入那么构造方法将不能覆盖由setter注入的值。很明显因为构造方法仅在对象被创建时调用setter注入有可能还不能保证某种依赖是否已经被注入也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下构造器注入不允许生成依赖关系不完整的对象
Spring框架中有哪些不同类型的事件 上下文更新事件 (ContextRefreshedEvent) 会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext接口中的refresh()方法时被触发 上下文开始事件 (ContextStartedEvent) 当容器调用ConfigurableApplicationContext的start()方法开始/重新开始容器时触发该事件 上下文停止事件 (ContextStoppedEvent) 当容器调用ConfigurableApplicationContext的stop()方法停止容器时触发该事件 上下文关闭事件 (ContextClosedEvent) 当ApplicationContext被关闭时触发该事件。容器被关闭时其管理的所有单例Bean都被销毁 请求处理事件 RequestHandledEvent) 在Web应用中当一个http请求(request)结束触发该事件。如果一个Bean实现了ApplicationListener接口当一个ApplicationEvent被发布以后bean会自动被通知 自定义事件 public class CustomApplicationEvent extends ApplicationEvent {public CustomApplicationEvent(Object source, final String msg) {super(source);System.out.println(Created a custom event.);}
}
// 为了监听这个事件还需要创建一个监听器
public class CustomEventListener implements ApplicationListenerCustomApplicationEvent {Overridepublic void onApplicationEvent(CustomApplicationEvent applicationEvent) {// handle event}
}
// 之后通过 applicationContext 接口的publishEvent() 方法来发布自定义事件
CustomApplicationEvent customEvent new CustomApplicationEvent(applicationContext, Test Message);
applicationContext.pulishEvent(customEvent);AOP (Aspect Oriented Program) 切面编程 AOP编程思想就是把这些横向性的问题和业务逻辑进行分离从而起到解耦的目的。 使用Aspect 定义切面类使用PointCut 定义切点
AOP通过两种方式实现 (没有默认实现的说法)
java动态代理 (被代理的类必须是接口) 生成的代理类的toString前缀是$Proxy生成字节码文件的字节数组 cglib动态代理 生成的代理类的toString前缀是CGLIB$ java动态代理为什么必须是接口因为代理类必须继承Proxy类所以不能继承用户类而只能是实现用户的接口 // AOP使用的代理实现根据判断条件而来没有默认使用其中一种的说法
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimized() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class? targetClass config.getTargetClass();if (targetClass null) {throw new AopConfigException(TargetSource cannot determine target class: Either an interface or a target is required for proxy creation)}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);} else {return new JdkDynamicAopProxy(config);}}
}// 创建上下文这里面通过后置处理器已经生成了代理对象
AnnotationConfigApplicationContext context new AnnotationConfigApplicatonContext(...);// 获取对象
UserService service context.getBean(UserSerivce.class);service.doSomething();
// 获取到的service不是原生对象是代理对象IOC容器
由程序代码直接操控的对象的调用权交给容器通过容器来实现对象组件的装配和管理。(通过工厂模式和反射机制实现) 。其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为回应容器适时的返回资源而应用了IOC 之后则是容器主动地将资源推送给它所管理的组件组件所要做的仅是选择一种合适的方式来接受资源这种行为也被称为查找的被动形式 IOC容器把对象注入进去的时候已经不是原生对象而是代理对象了。 IOC获取到实例对象的方式
XML注入注解注入
BeanFactory 与 ApplicationContext 有什么区别 BeanFactory和ApplicationContext是Spring的两大核心接口都可以当作Spring的容器。其中ApplicationContext是BeanFactory的子接口。 BeanFactory 是Spring里面最底层的接口包含了各种Bean的定义读取bean配置文件管理bean的加载实例化控制bean的生命周期维护bean之间的依赖关系。 ApplicationContext 作为BeanFactory的派生除了提供BeanFactory所具有的功能外还提供了更完整的框架功能。以下是三种常见的实现方式 ClassPathXmlAppliationContext从classpath的XML配置文件中读取上下文并生成上下文定义FileSystemXmlApplicationContext由文件系统中的XML配置文件读取上下文XmlWebApplicationContext由Web应用的XML文件读取上下文AnnotationConfigApplicationContext基于Java配置启动容器
Spring Bean的生命周期 实例化 Instantiation 属性赋值 Populate 初始化 Initialization 销毁 Destruction Spring提供了以下四种方式来管理Bean的生命周期事件 InitializingBean 和 DisposableBean 回调接口针对特殊行为的其它 Aware 接口Bean配置文件中的Custom init() 方法和 destroy() 方法beansbean iddemoBean classorg.newcih init-methodcustomInit destroy-methodcustomDestroy/
/beansPostConstruct 和 PreDestroy 注解方式
SpringMVC
MVC是软件架构模式是一种分离业务逻辑与显示页面的设计方法他把软件系统分为三个基本部分模型(Model)视图(View)控制器(Controller)。
控制器 对请求进行处理负责选择视图视图 用户与程序交互的界面模型 用于业务处理
原理
启动流程
如果在web.xml中配置了ContextLoaderListener那么Tomcat在启动的时候会先加载父容器并将其放到ServletContext中然后加载DispatcherServlet因为DispatcherServlet实质是一个Servlet所以会先执行它的init方法。这个init方法在HttpServletBean这个类中实现其主要工作是做一些初始化工作将我们在web.xml中配置的参数书设置到Servlet中然后再触发FrameWorkServlet的initServletBean方法FrameworkServlet主要作用是初始化Spring子上下文设置其父上下文并将其放入ServletContext中FrameworkServlet在调用initServletBean()的过程中同时会触发DispatcherServlet的onRefresh()方法这个方法会初始化SpringMVC的各个功能组件。比如异常处理器、视图处理器、请求映射处理
执行流程
发起请求到前端控制器 DispatcherServlet该控制器就会过滤出你哪些请求可以访问该servlet前端控制器会找到处理器映射器 HandlerMapping通过处理器映射器完成url到controller的映射通过映射器找到对应的处理器 Handler 并将处理器返回给前端控制器。(返回的处理器前有拦截器)前端控制器拿到处理器之后找到处理器适配器 HandlerAdapter通过适配器来访问和执行处理器。(不能直接访问处理器因为Spring的设计不知道调用哪个方法不知道处理器类如何创建出来的如注解等等)执行处理器处理器返回ModelAndView对象给处理器适配器 HandlerAdapter通过处理器适配器 HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet)前端控制器请求视图解析器 ViewResolver进行解析将ModelAndView的数据进行视图渲染。最后返回结果。
Spring常用注解
Controller/RestController 标注一个控制器类 RequestMapping 用来处理请求地址映射的注解 Resource 非Spring注解做Bean的注入默认按照名称注入也可指定类型 Autowired 自动注入按照类型装配依赖对象。如果想用按照名称搭配Qualifier Required 应用于设值方法它表明受影响的bean属性在配置时必须放在XML配置文件中否则容器就会抛出一个 BeanInitializationExeption 异常 ModelAttribute 该Controller所有方法调用前先执行此ModelAttribute方法可用于注解和方法参数中 SessionAttributes 把值放到session作用域中 PathVariable 用于将请求URL中的模板变量映射到功能处理方法的参数上 RequestParam 控制层获取参数 RequsetBody, ResponseBody 用于将Controller方法获取或返回的对象通过适当的HttpMessageConverter转换为指定格式 Componet 通用的注解标注组件 Repository 注解Dao层 Service 标注业务层组件类
SpringMVC设置重定向和转发
转发在返回值前面加forward:重定向在返回值前面加redirect:
SpringMVC的拦截器
SpringBoot
SpringCloud
通过适当的HttpMessageConverter转换为指定格式
Componet 通用的注解标注组件 Repository 注解Dao层 Service 标注业务层组件类
SpringMVC设置重定向和转发
转发在返回值前面加forward:重定向在返回值前面加redirect:
SpringMVC的拦截器
SpringBoot
SpringCloud