校招面经(四)

35 阅读6分钟

Spring

对Spring的IoC和AOP的理解?

IoC(控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC在其他语言中也有应用,并非Spring特有的。IoC容器是Spring用来实现IoC载体,IoC容器实际上就是个Map<Key,Value>,Map中存放的是各种对象。将对象之间的依赖关系交给IoC容器来管理,并由IoC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从一个复杂的依赖关系中解放出来。IoC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件或者注解,完全不用考虑对象是如何被创建出来的

AOP(面向切面编程)能将那些与业务无关,却为业务模块共同调用的逻辑或责任(例如,事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块的耦合度,并有利于未来的可拓展性和可维护性。SpringAOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么SpringAOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用JDK Proxy去进行代理,这时候Spring AOP会使用Cglib,生成一个被代理对象的子类作为代理。Spring中的事务也是通过AOP来实现的

IoC实现原理?

它是通过反射机制+工厂模式实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中

控制反转就是:获得依赖对象的方式反转了。

1、依赖注入发生的时间

(1).用户第一次通过 getBean 方法向 IoC 容索要 Bean 时, IoC 容器触发依赖注入。 (2).当用户在 Bean 定义资源中为元素配置了 lazy init 属性,即让容器在解析注册 Bean 定义时进行预实例化,触发依赖注入。

2、依赖注入实现在以下两个方法中

(1).createBeanInstance:生成Bean所包含的java对象实例。 (2).populateBean:对Bean属性的依赖注入进行处理。

IoC的加载过程?

定位资源文件(XML,@Configuration,注解),然后就是对资源文件的解析,接着将最终解析的结果封装为BeanDefinitionBuilder。其次,还需要在BeanFactory中完成Bean的注册,也就是将BeanDefinition的Name和实例封装到一个Map里。当注册完成之后,在BeanFatory的getBean()方法中完成初始化。这个时候应用程序就可以直接使用Bean了

JDK的动态代理怎么实现的?

中介实现类InnvocationHandler接口,实现invoke方法。通过newProxyInstance创建出代理对象,参数是ClassLoader、interface、InnvocationHandler对象

Spring框架用到了哪些设计模式?

工厂设计模式 : Spring使用工厂模式通过BeanFactory、ApplicationContext创建bean对象。

代理设计模式: Spring AOP功能的实现。

单例设计模式: Spring中的Bean默认都是单例的。

模板方法模式: Spring中jdbcTemplate、 hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

包装器设计模式: 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

观察者模式: Spring事件驱动模型就是观察者模式很经典的一个应用。

适配器模式:Spring AOP的增强或通知(使用到了适配器模式、spring MVC中也是用到了适配器模式适配Controller。

Spring容器启动过程有哪些步骤?

1、 初始化一个Reader和Scanner Reader可以用来注册单个BeanDefinition Scanner用来扫描得到的BeanDefinition

2、 通过Reader把配置类注册成为一个BeanDefinition

3、 调用refresh方法,开始启动 Spring 容器

4、 先获取一个Bean工厂

5、 预先往Bean工厂中添加一些 Bean 后置处理器和一些单例Bean ,和一些其他的配置

6、 执行Bean工厂的后置处理器,这里会进行扫描,扫描bean 和bean的后置处理器

7、 实例化bean的后置处理器并排序,然后添加到Bean工厂中去

8、 初始化用来进行国际化的MessageSource

9、 初始化事件广播器

10、 注册事件监听器

11、 开始实例化非懒加载的单例bean

12、 发布ContextRefreshedEvent事件

@RestController和@Controller的区别?

单独使用@Controller不加@ResponseBody的话一般使用在要返回一个视图的情况,这种情况属于比较传统的Spring MVC的应用,对应于前后端不分离的情况,直接返回一个页面。

@RestController只返回对象,对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response) 中,这种情况属于 RESTful Web 服务,这也是目前日常开发所接触的最常用的情况(前后端分离)。

@Component和@Bean的区别?

1、 作用对象不同 : @Component注解作用于类,而@Bean注解作用于方法。

2、 @Component 通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中 (我们可以使用@ComponentScan注解定义要扫描的路径从中找出标识了需要装配的类自动装配到Spring的bean 容器中)。

@Bean注解通常是我们在标有该注解的方法中定义产生这个bean,@Bean告诉了Spring这是某个类的实例,当我需要用它的时候还给我。

3、 @Bean注解比Component注解的自定义性更强,而且很多地方我们只能通过@Bean注解来注册bean。比如当我们引用第三方库 中的类需要装配到Spring容器时,则只能通过@Bean来实现。

Bean的生命周期?

1、Bean容器找到配置文件中Spring Bean的定义

2、 Bean容器利用反射创建一个Bean的实例

3、 对对象中加了 @Autowired注解的属性进行属性填充

4、 如果实现了Aware系列回调方法,则调用回调Aware方法,比如BeanNameAware和BeanFactoryAware

5、 然后调用BeanPostProcessor的初始化前方法、初始化方法、初始化后 的方法,在初始化后的方法里会进行AOP

6、如果当前创建的Bean是单例的 ,则会把这个Bean放到单例池中

7、然后就可以使用这个Bean了,Spring容器关闭的时候会调用 DiposableBean中的destory方法