什么是AOP?
AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring AOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。
当然也可以使用AspectJ,Spring AOP中已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。使用AOP之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能、事务管理和权限管理等场景都用到了AOP—摘自《Java圣经》
为什么需要AOP?
解耦。
将记录日志功能解耦为日志切面,它的目标是解耦。进而引出AOP的理念:就是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
什么是IoC?
(1)IOC就是控制反转,是指创建对象的控制权的转移。以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系。对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
(2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
(3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。
—摘自《Java圣经》
为什么需要IoC?
- 一方面,可以简化开发的流程。比如说,一个类有100个对象成员,这样的类又要在不同的地方实例化100次,这就是很费手脚的,结合IOC和自动依赖注入,就能够省掉中间这些对象成员的注入过程,提升我们的开发效率。
- 另一方面,如果想替换掉某个组件的实现,所有的依赖这个组件的代码就都要修改,也很麻烦。我们把系统中所有的组件放进一个“容器”中统一管理,需要使用组件的地方都通过容器来获取,这样替换组件就会很容易。
如果没有Spring框架,我们需要自己创建User/Dao/Service等,比如:
UserDaoImpl userDao = new UserDaoImpl();
UserSericeImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
List<User> userList = userService.findUserList();
有了Spring框架,可以将原有Bean的创建工作转给框架, 需要用时从Bean的容器中获取即可,这样便简化了开发工作.更进一步,你便能理解为何会有如下的知识点了:
- Spring框架管理这些Bean的创建工作,即由用户管理Bean转变为框架管理Bean,这个就叫控制反转 - Inversion of Control (IoC)
- Spring 框架托管创建的Bean放在哪里呢? 这便是IoC Container;
- Spring 框架为了更好让用户配置Bean,必然会引入不同方式来配置Bean? 这便是xml配置,Java配置,注解配置等支持
- Spring 框架既然接管了Bean的生成,必然需要管理整个Bean的生命周期等;
- 应用程序代码从Ioc Container中获取依赖的Bean,注入到应用程序中,这个过程叫 依赖注入(Dependency Injection,DI) ; 所以说控制反转是通过依赖注入实现的,其实它们是同一个概念的不同角度描述。通俗来说就是IoC是设计思想,DI是实现方式
- 在依赖注入时,有哪些方式呢?这就是构造器方式,@Autowired, @Resource, @Qualifier… 同时Bean之间存在依赖(可能存在先后顺序问题,以及循环依赖问题等)
如何实现IoC?
以下是实现IoC的一些常见方法:
-
依赖注入(DI):DI是IoC的一种实现方式,它通过将依赖关系注入到对象中来实现控制反转。依赖可以通过构造函数、属性或方法参数进行注入。
-
工厂模式:工厂模式是一种创建对象的设计模式,它将对象的实例化过程封装在工厂类中。通过使用工厂方法或抽象工厂,应用程序可以将对象的创建和管理委托给工厂,从而实现IoC。
-
服务定位器模式:服务定位器模式是一种设计模式,它使用一个中心注册表(服务定位器)来解耦组件之间的依赖关系。组件可以从服务定位器中获取它们所需的依赖项,而不必直接引用它们。
-
模块化设计:通过将应用程序拆分为模块或组件,每个模块都有清晰定义的接口和依赖关系,可以实现IoC。模块之间的通信和依赖由容器或框架进行管理。
-
Aspect-Oriented Programming(AOP):AOP是一种编程范式,它允许开发人员在应用程序中定义横切关注点(如日志记录、事务管理等),并将它们与核心业务逻辑分离。通过将横切关注点与业务逻辑分离,AOP可以实现IoC。
什么是new对象?
在面向对象编程中,使用关键字 new 创建一个对象的实例称为 “new 对象”。这个过程通常被称为实例化类(Instantiating a Class)。在许多编程语言中,new 关键字用于创建一个类的新实例,即一个对象。在创建对象时,会调用该类的构造函数来初始化对象的状态。
为什么需要new对象?
在面向对象编程中,使用 new
关键字创建对象的实例有几个重要的原因:
-
创建多个实例:通过
new
关键字,可以在程序运行时创建多个对象的实例,每个实例都有自己的状态和行为。这使得我们可以有效地管理不同的数据和逻辑单元。 -
封装数据和行为:对象是面向对象编程的基本单元,它封装了数据(属性)和行为(方法)。通过创建对象的实例,我们可以将相关的数据和行为组织在一起,实现更清晰、更模块化的代码结构。
-
实现抽象和继承:通过创建对象的实例,可以利用抽象类和接口定义通用的行为,并通过继承和实现来扩展和定制具体的功能。这种面向对象的设计方式提高了代码的可重用性和可扩展性。
-
管理对象的生命周期:通过
new
关键字创建的对象实例由程序员控制其生命周期,可以在需要时创建、使用和销毁对象。这种精确的控制可以帮助优化内存和资源的使用。 -
提高代码可读性和可维护性:使用
new
关键字创建对象实例可以使代码更易于理解和维护。通过创建明确定义的对象,可以提高代码的可读性,并使程序的逻辑更加清晰和可靠。
总之,new
关键字是面向对象编程中创建对象实例的重要工具,它使我们能够有效地利用对象的封装、抽象、继承和多态等特性,编写出更加模块化、可重用和可维护的代码。
什么是DI?
DI(Dependency Injection,依赖注入)是一种软件设计模式,用于降低类之间的耦合度,并使代码更易于理解、测试和维护。在依赖注入模式中,对象不再负责创建或管理它们所依赖的对象,而是由外部组件(通常是一个容器或框架)负责将依赖项注入到对象中。 依赖注入有三种常见的形式:
-
构造函数注入(Constructor Injection):通过类的构造函数将依赖项传递给对象。在实例化对象时,依赖项通过构造函数参数传递进入对象。
-
属性注入(Setter Injection):通过公共属性的 setter 方法将依赖项注入到对象中。
-
接口注入(Interface Injection):对象实现一个特定的接口,该接口包含一个方法,用于将依赖项注入到对象中。
通过使用依赖注入,可以实现以下好处:
- 松耦合:对象之间的依赖关系通过外部容器动态注入,减少了类之间的紧耦合,提高了代码的灵活性和可维护性。
- 可测试性:依赖项可以轻松地被替换为模拟对象,从而使单元测试更容易编写和执行。
- 可重用性:通过依赖注入,可以更容易地重用和组合对象,从而提高了代码的可重用性。
- 可读性:依赖注入可以使代码更加清晰和易于理解,因为它明确地显示了类之间的依赖关系。
综上所述,依赖注入是一种强大的设计模式,可以帮助管理类之间的依赖关系,从而提高代码的质量和可维护性。
什么是Bean?
在Java中,Bean 是一种特殊的类,通常用于表示应用程序中的实体或数据对象。Bean 类具有以下特征:
-
无参构造函数:Bean 类通常提供一个无参构造函数,以便在实例化时使用。这样的构造函数可以通过
new
关键字直接创建 Bean 的实例。 -
私有字段:Bean 类通常包含一些私有字段(成员变量),这些字段用于表示对象的状态或属性。
-
公共访问方法:为了访问和修改私有字段,Bean 类通常提供公共的 getter 和 setter 方法。这些方法允许其他类读取和设置 Bean 对象的状态。
-
可序列化:有时,Bean 类需要实现 Serializable 接口,以便对象可以在网络上传输或保存到文件中。
-
遵循特定的命名约定:Bean 类的命名通常遵循特定的命名约定,例如使用驼峰命名法,属性名和字段名相同等。
Bean 通常用于表示业务逻辑中的实体或数据对象,例如用户、订单、产品等。在 Java 开发中,常见的 Bean 类可以是普通 Java类、JavaBeans(符合 JavaBean 规范的类)、POJO(Plain Old Java Object)等。
JavaBean 是一种特殊类型的 Bean,它严格遵循 JavaBean 规范,包括具有无参构造函数、提供 getter 和 setter方法等。JavaBean 的特点是易于使用和重用,因此在 Java 开发中经常被广泛应用于表示数据对象。
什么是Spring框架?
Spring是一种轻量级框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们一般说的Spring框架就是Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。比如Core Container中的Core组件是Spring所有组件的核心,Beans组件和Context组件是实现IOC和DI的基础,AOP组件用来实现面向切面编程。Spring官网列出的Spring的6个特征:
- 核心技术:依赖注入(DI),AOP,事件(Events),资源,i18n,验证,数据绑定,类型转换,SpEL。
- 测试:模拟对象,TestContext框架,Spring MVC测试,WebTestClient。
- 数据访问:事务,DAO支持,JDBC,ORM,编组XML。
- Web支持:Spring MVC和Spring WebFlux Web框架。
- 集成:远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。
- 语言:Kotlin,Groovy,动态语言。
列举一些重要的Spring模块?
下图对应的是Spring 4.x的版本,目前最新的5.x版本中Web模块的Portlet组件已经被废弃掉,同时增加了用于异步响应式处理的WebFlux组件。
- Spring Core:基础,可以说Spring其他所有的功能都依赖于该类库。主要提供IOC和DI功能。
- Spring Aspects:该模块为与AspectJ的集成提供支持。
- Spring AOP:提供面向切面的编程实现。
- Spring JDBC:Java数据库连接。
- Spring JMS:Java消息服务。
- Spring ORM:用于支持Hibernate等ORM工具。
- Spring Web:为创建Web应用程序提供支持。
- Spring Test:提供了对JUnit和TestNG测试的支持。
什么是IOC? 如何实现的?
IOC(Inversion Of Controll,控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交给IOC容器来管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
Spring 中的 IoC 的实现原理就是工厂模式加反射机制。
interface Fruit {
public abstract void eat();
}
class Apple implements Fruit {
public void eat(){
System.out.println("Apple");
}
}
class Orange implements Fruit {
public void eat(){
System.out.println("Orange");
}
}
class Factory {
public static Fruit getInstance(String ClassName) {
Fruit f=null;
try {
f=(Fruit)Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class Client {
public static void main(String[] a) {
Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");
if(f!=null){
f.eat();
}
}
}
什么是AOP? 有哪些AOP的概念?
AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。
Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring AOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。
当然也可以使用AspectJ,Spring AOP中已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。使用AOP之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能、事务管理和权限管理等场景都用到了AOP。
AOP包含的几个概念
- Jointpoint(连接点):具体的切面点点抽象概念,可以是在字段、方法上,Spring中具体表现形式是PointCut(切入点),仅作用在方法上。
- Advice(通知): 在连接点进行的具体操作,如何进行增强处理的,分为前置、后置、异常、最终、环绕五种情况。目标对象:被AOP框架进行增强处理的对象,也被称为被增强的对象。
- AOP代理:AOP框架创建的对象,简单的说,代理就是对目标对象的加强。Spring中的AOP代理可以是JDK动态代理,也可以是CGLIB代理。
- Weaving(织入):将增强处理添加到目标对象中,创建一个被增强的对象的过程
总结为一句话就是:在目标对象(target object)的某些方法(jointpoint)添加不同种类的操作(通知、增强操处理),最后通过某些方法(weaving、织入操作)实现一个新的代理目标对象。
有哪些AOP Advice通知的类型?
特定 JoinPoint 处的 Aspect 所采取的动作称为 Advice。Spring AOP 使用一个 Advice 作为拦截器,在 JoinPoint “周围”维护一系列的拦截器。
- 前置通知(Before advice) : 这些类型的 Advice 在 joinpoint 方法之前执行,并使用 @Before 注解标记进行配置。
- 后置通知(After advice) :这些类型的 Advice 在连接点方法之后执行,无论方法退出是正常还是异常返回,并使用 @After 注解标记进行配置。
- 返回后通知(After return advice) :这些类型的 Advice 在连接点方法正常执行后执行,并使用@AfterReturning 注解标记进行配置。
- 环绕通知(Around advice) :这些类型的 Advice 在连接点之前和之后执行,并使用 @Around 注解标记进行配置。
- 抛出异常后通知(After throwing advice) :仅在 joinpoint 方法通过抛出异常退出并使用 @AfterThrowing 注解标记配置时执行。
AOP 有哪些实现方式?
实现 AOP 的技术,主要分为两大类:
- 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
- 编译时编织(特殊编译器实现)
- 类加载时编织(特殊的类加载器实现)。
- 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
- JDK 动态代理 JDK Proxy 是 Java 语言自带的功能,无需通过加载第三方类实现;
- Java 对 JDK Proxy 提供了稳定的支持,并且会持续的升级和更新,Java 8 版本中的 JDK Proxy 性能相比于之前版本提升了很多;
- JDK Proxy 是通过拦截器加反射的方式实现的;
- JDK Proxy 只能代理实现接口的类;
- JDK Proxy 实现和调用起来比较简单;
- CGLIB CGLib 是第三方提供的工具,基于 ASM 实现的,性能比较高;
- CGLib 无需通过接口来实现,它是针对类实现代理,主要是对指定的类生成一个子类,它是通过实现子类的方式来完成调用的。
Spring中的bean的作用域有哪些?
- singleton:唯一bean实例,Spring中的bean默认都是单例的。
- prototype:每次请求都会创建一个新的bean实例。
- request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
- session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。
- global-session:全局session作用域,仅仅在基于Portlet的Web应用中才有意义,Spring5中已经没有了。Portlet是能够生成语义代码(例如HTML)片段的小型Java Web插件。它们基于Portlet容器,可以像Servlet一样处理HTTP请求。但是与Servlet不同,每个Portlet都有不同的会话。
Spring中的bean生命周期?
- 实例化:在这个阶段,Spring容器通过反射机制创建Bean的实例。
- 属性设置:在这个阶段,Spring容器设置Bean的属性。
- 初始化:在这个阶段,Spring容器调用Bean的初始化方法,如果定义了的话。
- 使用:在这个阶段,Spring容器将Bean提供给应用程序使用。
- 销毁:在这个阶段,Spring容器调用Bean的销毁方法,如果定义了的话。
说说自己对于Spring MVC的了解?
MVC是一种设计模式,Spring MVC是一款很优秀的MVC框架。Spring MVC可以帮助我们进行更简洁的Web层的开发,并且它天生与Spring框架集成。Spring MVC下我们一般把后端项目分为Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。
Spring MVC的工作原理了解嘛?
流程说明:
- 客户端(浏览器)发送请求,直接请求到DispatcherServlet
- DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
- 解析到对应的Handler(也就是我们平常说的Controller控制器)。
- HandlerAdapter会根据Handler来调用真正的处理器来处理请求和执行相对应的业务逻辑。
- 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是逻辑上的View。
- ViewResolver会根据逻辑View去查找实际的View。
- DispatcherServlet把返回的Model传给View(视图渲染)。
- 把View返回给请求者(浏览器)。
Spring框架中用到了哪些设计模式?
- 工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。
- 代理设计模式:Spring AOP功能的实现。
- 单例设计模式:Spring中的bean默认都是单例的。
- 模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式。
- 包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、Spring MVC中也是用到了适配器模式适配Controller。
将一个类声明为Spring的bean的注解有哪些?
我们一般使用@Autowired注解去自动装配bean。而想要把一个类标识为可以用@Autowired注解自动装配的bean,可以采用以下的注解实现:
- @Component注解。通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪一个层,可以使用@Component注解标注。
- @Repository注解。对应持久层,即Dao层,主要用于数据库相关操作。
- @Service注解。对应服务层,即Service层,主要涉及一些复杂的逻辑,需要用到Dao层(注入)。
- @Controller注解。对应Spring MVC的控制层,即Controller层,主要用于接受用户请求并调用Service层的方法返回数据给前端页面
Spring、Spring MVC和SpringBoot有什么区别?
- Spring
Spring最重要的特征是依赖注入。所有Spring Modules不是依赖注入就是IOC控制反转。当我们恰当的使用DI或者是IOC的时候,可以开发松耦合应用。 - Spring MVC
Spring MVC提供了一种分离式的方法来开发Web应用。通过运用像DispatcherServelet,ModelAndView 和 ViewResolver 等一些简单的概念,开发 Web 应用将会变的非常简单。 - SpringBoot
Spring和Spring MVC的问题在于需要配置大量的参数。SpringBoot通过一个自动配置和启动的项来解决这个问题。
SpringBoot自动配置的原理?
在Spring程序main
方法中,添加@SpringBootApplication
或者@EnableAutoConfiguration
会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建的Spring容器中的bean。
Spring Boot的核心注解是哪些?他主由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication
,他也是SpringBoot的核心注解,主要组合包含了以下3个注解:
@SpringBootConfiguration
:组合了@Configuration
注解,实现配置文件的功能;@EnableAutoConfiguration
:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置的功能:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class});
@ComponentScan
:Spring组件扫描。
SpringBoot的核心配置文件有哪几个?他们的区别是什么?
SpringBoot的核心配置文件是application和bootstrap配置文件。
application配置文件这个容易理解,主要用于Spring Boot项目的自动化配置。bootstrap配置文件有以下几个应用场景:
- 使用Spring Cloud Config配置中心时,这时需要在bootstrap配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;
- 一些固定的不能被覆盖的属性;
- 一些加密/解密的场景;
SpringBoot 实现热部署有哪几种方式?
- Spring Loaded
- Spring-boot-devtools