Java面试-框架篇(一)Spring面试详解

破局之路课程 2024-03-24 14:57:45
一、什么是Spring IOC容器

Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。

依赖注入:

在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码 中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC 容器将它们装配在一起。

注入方式:

构造函数注入 、setter 注入 、接口注入, 在 Spring Framework 中,仅使用构造函数和 setter 注入。

Ioc实现的主要机制就是工厂模式+反射。

二、BeanFactory和 ApplicationContext

beanFactory:

1、是Spring最底层的接口,提供了简单的容器功能,实例化对象和拿对象的功能。

2、懒加载bean,启动不加载,调用时再去加载

3、不支持国家化

4、不支持依赖的注解

ApplicationContext:

1、应用上下文继承自BeanFactory接口,他是Spring更高级的一种容器。

2、启动时初始化所有的Bean,即时加载。

3、支持国际化

4、支持依赖的注解

三、聊一聊Spring Bean

它们是构成用户应用程序主干的对象。 · Bean 由 Spring IoC 容器管理。 · 它们由 Spring IoC 容器实例化,配置,装配和管理。 · Bean 是基于用户提供给容器的配置元数据创建。

Bean的5中Scope:

1、Singleton 每个Spring Ioc容器仅用一个bean

2、Propotype:每次请求都会产生新的Bean

3、Request:每次HTTP请求产生一个新的实例

4、Session:类似于标准的HTTP Session作用域

Spring Bean生命周期:

1、Spring容器根据配置中的bean定义实例化的bean。

2、Spring使用依赖注入填充所有属性,如bean中所定义的属性。

3、如果 bean 实现BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用setBeanName()。

4、如果bean实现了BeanFactoryAware接口,则工厂通过传递自身的实例对象来调用setBeanFactory()。

5、如果存在bean关联的任何BeanPostProcessor,则调用preProcessorBeforeInitialization()方法。

6、如果bean指定了init方法(bean标签下的init-method属性),那么将调用他。

7、最后如果存在bean关联的任何BeanPostProcessor,则调用PostProcessorAfterInitialization方法。

8、如果bean实现了DisposableBean接口,当spring容器关闭时,会调用destroy方法。

9、如果bean指定了destroy方法(bean标签下的destroy-method属性),那么将调用它。

四、@Component, @Controller, @Repository,@Service 有何区别?

@Repository:持久层,用于标注数据访问组件,即DAO组件。

@Service:业务层,用于标注业务逻辑层主键。

@Controller:控制层,用于标注控制层组件。

@Component:当你不确定是属于哪一层的时候使用

从@service的源码看,service仍然是使用了@Component注解(@Controller与@Repository与service一样,这里就不贴源码了)。

component即组件,相当于xml配置文件中的bean申明,通过spring的自动扫描机制,在规定的类路径中寻找标注了@Component,@Service,@Repository,@Controller注解的类,并把这些类纳入进容器中进行管理。getBean的默认名称是类名(头字母小写),并且是单例的,如果想自定义,可以使用@Service(“beanName”)@Scope(“prototype”)来改变。

五、常用注解释义

@Required 应用于 bean 属性 setter 方法。此注解仅指示必须在配置时使用bean 定义中的显式属性值或使用自动装配填充受影响的 bean 属性。如果尚未填充受影响的 bean 属性,则容器将抛出 BeanInitializationException。

@Autowired 可以更准确地控制应该在何处以及如何进行自动装配。此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配bean。类型驱动注入。

@Qualifier:指定bean的name,当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean来消除歧义。

@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。

@Resource的装配顺序:

(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配

(2)、指定了name或者type则根据指定的类型去匹配bean

(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错

然后,区分一下@Autowired和@Resource两个注解的区别:

(1)、@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配

(2)、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了

Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。

@Scope注解 作用域

@Lazy(true) 表示延迟初始化

@Scope用于指定scope作用域的(用在类上)

@PostConstruct用于指定初始化方法(用在方法上)

@PreDestory用于指定销毁方法(用在方法上)

@DependsOn:定义Bean初始化及销毁时的顺序

@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常

@Async异步方法调用

六、什么是AOP

AOP(Aspect-Oriented Programming), 即 面向切面编程, 它与OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与OOP 不同的抽象软件结构的视角. 在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面)

Aop应用举例:日志、事务、权限、缓存。

AOP相关概念:

(1)横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点

(2)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(3)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用。被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

(4)Advice(通知):AOP在特定的切入点上执行的增强处理,有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕)

(5)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(6)weave(织入):将切面应用到目标对象并导致代理对象创建的过程

(7)introduction(引入):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

(8)AOP代理(AOP Proxy):AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

(9)目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

通知类型介绍:

1、before:在目标方法被调用之前做增强处理。

2、afterReturning:在目标方法正常完成后做增强,除了指定切入点表达式后,还可以指定returning的返回值值形参名,代表目标方法的返回值。

3、AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象

4、After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

5、Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

什么是静态代理:

由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

什么是动态代理

1.代理对象,不需要实现接口

2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

3.动态代理也叫做:JDK代理,接口代理

JDK动态代理

1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)

2)实现方式:

A、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);

B、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});

C、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

D、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

缺点:jdk动态代理,必须是面向接口,目标业务类必须实现接口

CGLIB动态代理

原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

什么是CGLIB动态代理

使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码

CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

Spring中:

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

0 阅读:0

破局之路课程

简介:感谢大家的关注