概述:Spring框架作为一款轻量级的开发框架,为Java开发提供组件化的管理服务,降低组件间的耦合度,并简化了第三方JavaEE中间件的使用(Spring框架集成),它主要有两大核心思想:IOC(控制反转)和AOP(面向切面编程)。
一、IOC
IOC:(Inversion of Control,中文释义:控制反转 ) 是Spring框架的核心思想之一,主要用于解耦。IOC是指将创建对象的控制权转移给Spring框架进行管理。由Spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之间的依赖关系。使对象之间形成松散耦合的关系,实现解耦;
○控制 :指的是对象创建(实例化、管理)的权力
○反转 :控制权交给外部环境(Spring框架、IoC容器)
在某个Java对象(调用者)需要调用另一个Java对象(被调用者)时,传统编程模式下,调用者通常会采用“new 被调用者”的代码方式来创建对象,这方式会增加调用者与被调用者之间的耦合性,不利于后期代码的升级与维护。而Spring框架出现后IOC思想下,对象的实例不再由调用者来创建,而是有Spring容器来创建,同时负责控制对象间的关系。
IOC将对象的创建交给Spring容器,其中属性的依赖问题它也会帮我们进行完成,这里需要提到实现IOC的一种方式DI:
DI(Dependecy Inject,中文释义:依赖注入) 是对IOC概念的不同角度的描述。给对象属性赋值,IOC是一种设计思想,而DI是实现这种思想的一种创建方式,将一 起工作具有关系的对象之间,通过set方法和构造器给对象属性注入值,以此来维护对象之间的关系。
依赖注入的方式:
1、构造方法注入
2、set方法注入
1、为Student类中提供有参构造方法(用于构造注入)、set方法(set注入)
2、在applicationContext.xml文件中配置bean
测试:在Spring容器中去获取id为stu的Bean对象并打印
注意:
在通过有参构造方法注入值时,提供了有参构造方法后,Java就不在帮我们提供默认的无参构造了,我们最好再显示定义一个无参构造,否则当你采用不同的注入方式初始化bean对象时会抛出异常,告诉你Unsatisfied dependency expressed through constructor parameter 0。
通过set方法注入会先利用配置的bean的Class反射创建出一个bean实例,再通过set方法注入值
二、AOP
AOP:(Aspect-Oriented Programming: 面向切面编程)是OOP面向对象思想的延伸,将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect)。它是一种横向的抽取方式,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;
SpringAOP中常用专业术语(通俗版):(1)切面:切点+通知
(2)连接点:切面中的方法都可以被视为切入点【选项卡】
(3)切入点:所选择的要进行织入操作的方法【选择的选项】
(4)通知(增强处理):为切入点增强所要执行的程序代码
(5)目标对象:被代理/需要加强的类
(6)织入:为切入点加上通知的过程
根据Spring中通知在目标来方法的连接点位置,通知分为5种:
1、前置通知@Before:在目标方法执行前实施增强
2、返回通知@AfterReturning:在目标方法执行成功后实施增强【成功执行】
3、后置通知@After:在目标方法执行后实施增强【无论成功与否均执行】
4、异常通知@AfterThrowing:在目标方法执行抛出异常时实施增强【异常执行】
5、环绕通知@Around:在目标方法前后均可执行,可以包围目标方法进行自定义
下面基于com.apesource.service.ServiceImp类进行方法增强
步骤1:@Aspect修饰定义切面类并@Component注入容器
步骤2:@PointCut定义切点【使用切点表达式】
步骤3:定义各种通知作用于切点
ServiceImp类代码如下:
测试代码:重点关注环绕通知,测试时注释调上面四个通知代码输出更加清晰
1、测试add(),其中模拟了算数异常ArithmeticException
目标方法执行抛出异常,异常通知会执行,返回通知不执行
2、测试delete(),程序会执行成功
目标方法执行成功,异常通知不会执行,返回通知执行
SpringAOP的实现方式:
●Spring AOP 基于动态代理实现:
○如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
○如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);
应用场景:当我们的业务方法中需要做事务管理/日志记录等操作,且多个业务都需要添加此操作时,OOP的设计思想无法解决冗余,通过AOP可以解决这种横向代码冗余问题。