Spring IOC和AOP

简介: Spring IOC和AOP

IOC部分:

1.Spring是什么?

Spring是一个生态,可以构建java应用所需要的一切基础设施。通常spring指的是spring frameWork.

一般的生态来说:

  • 1.Spring FrameWork
  • 2.SpringBoot
    增加了自动配置
    总结一下,其实就是 SpSpring Boot 在启动的时候,按照约定去读取 Spring Boot Starter 的配置信息,再根据配置信息对资源进行初始化,并注入到 Spring 容器中。这样 Spring Boot 启动完毕后,就已经准备好了一切资源,使用过程中直接注入对应 Bean 资源即可
  • 3.SpringMVC
  • 4.SpringCloud
    分布式的springboot,适用于分布式

而spring 是一个轻量级开源框架:

IOC:控制翻转

AOP:面向切面编程


2 .IOC控制反转

本意: 对象的创建由我们自己new转到了spring ioc容器中,由spring ioc容器统一管理、

这样的好处: 降低对象间的耦合度

底层分析: xml配置文件、反射、简单工厂模式

我们通过读取xml配置文件(bean id+class),通过读取类的全路径,来进行反射创建对象,然后这个过程是由spring ioc完成的,我们只需要调用它提供的方法即可获得对象,这是简单工厂模式。


3.IOC的两种实现

1)BeanFactory接口

这个接口是基本实现,一般不提供开发人员使用,并且加载配置文件的时候是懒加载,不会创建对象。

2)ApplicationContext接口(其中实现的是BeanFactory接口)

这个接口是提供给开发人员使用的,有相对多的功能,加载配置文件的就会创建对象,所以相对式慢启动、快响应。


4.Bean的管理

1)创建对象

2)为对象设置属性

一般分为基于xml的配置文件和基于注解方式的实现:

xml文件:

创建对象:在xml文件配置bean注入属性(DI):构造注入/设置注入(set),可以注入简单属性的值,也可以注入其他类的对象,包括注入外部bean、注入内部bean、

基于注解:

创建对象:在xml文件配置component-scan,然后再要创建对象的类上加入注解:@component、@service、@Reposity、@Controller

注入属性(DI):在属性上加入注解:@Autowire、@Vlaue、@Qualifier、@Resource


5:DI和IOC

可以看到IOC式控制翻转,主要是创建对象的思想,而真正的实现是由反射+简单工厂,然后通过DI技术实现对象的属性赋值


6.scope

一般是单例、可以设置多例、还有不常用session、request,一次请求创建一个bean,一个会话创建一个bean


7.spring的单例安全

单例:一般如果涉及到无状态的bean(没有属性),那么肯定用单例,并且安全

但是如果有状态的bean,单例则不安全了,我们一般用多例模式;当然还可以在单例模式下设置属性ThreadLocal来保证每个线程有自己的属性。


8.spring bean的常见生命周期

简单来说:

创建对象---->注入属性---->后置处理器的Before方法------>初始化方法-------->后置处理器的After方法------>获得对象

销毁对象------>调用destory方法(写了才有用)

为了更好理解,可以重构成实例化、属性注入、初始化、销毁四个主要部分,其余部分相当于使用AOP技术,如果实现了相关接口,才会有这些过程。

·1.BeanFactoryPostProcessor的bean定义

BeanFactoryPostProcessor接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以随心所欲的修改属性

·2.InstantiationAwareBeanPostProcessor的bean定义

postProcessBeforeInstantiation方法

·3.实例化

·4.InstantiationAwareBeanPostProcessor的bean定义

postProcessAfterInstantiation方法

·5.注入属性

·6.Aware接口

【BeanNameAware接口】调用BeanNameAware.setBeanName()

【BeanFactoryAware】调用BeanFactoryAware.setBeanFactory()

【ApplicationContextAware】调用ApplicationContextAware.setApplicationContext()

·7.BeanPostProcessor的bean定义

postProcessBeforeInitialization方法

·8.InitializingBean的接口

InitializingBean.afterPropertiesSet()方法

·9.初始化init

·10.BeanPostProcessor的bean定义

postProcessAfterInitialization方法

·11.DisposableBean接口

destroy()方法

·12.自定义init_destory()方法

9.Spring 怎么解决循环依赖问题?

  • 三级缓存
  • singletonObjects 一级缓存
  • earlySingletonObjects 二级缓存
  • singletonFactories 三级缓存

情景一(没有循环依赖)----一级缓存

情景二(有循环依赖,没有Aop) -----二级缓存

最后把半成品池(二级缓存)的对象销毁;

注:无法解决Aop代理对象

情景三(有循环依赖,有Aop)----三级缓存

步骤:(待)


https://blog.csdn.net/lkforce/article/details/97183065

https://blog.csdn.net/m0_43448868/article/details/113578628

https://www.bilibili.com/video/BV1ET4y1N7Sp?p=1

参考链接:

https://www.nowcoder.com/discuss/747711

https://blog.csdn.net/qq_36714200/article/details/111240510

AOP部分

1.AOP

面向切面编程,

主要本质: 对业务逻辑的各个部分进行分离,从而业务逻辑和一些其他非业务逻辑:事务、日志等分隔开,同理降低耦合度,并且代码的复用能力。

2.静态代理和动态代理

静态代理:

对一个类,我们利用其对象来调用其方法,但是我们生成一个代理类,这个代理类作为其访问的接口,并且我们可以在其对象方法前后加上自己的新的逻辑功能,进行增强。— 编译时完成

动态代理:

不同于静态代理,我们在运行时进行动态代理类的生成,主要分为两种:

1)基于JDK

接口+实现类

主要是反射实现的,代理类Proxy,主要是三个参数(实现类的类加载器、实现类的接口、实现invocationhandler接口的对象(实现类对象)

2)基于CGLIB

没有接口,只有实现类,通过ASM开源包

对代理对象类的class文件加载进来,通过修改字节码生成子类处理。因此如果被代理类被final关键字所修饰,会失败。

内部是实现”MethodInterceptor“接口,而这个接口内部获得实现类的元对象,并把它设置为Enhance类的父类,所以这是继承的思想,在其字节码中的指定对象前后加入自己处理逻辑。

3)对比

cglib的创建效率低,调用效率高;而spring默认是jdk代理,但是如果没有实现接口,则强制使用CGLib来实现动态代理。


3.spring的常用设计模式

1)简单工厂模式—IOC

2)单例模式—bean

3)动态代理----AOP


4.AOP的实现

术语:

连接点:类中的方法(不用记)

切入点:这个才有用,真正被增强的方法

切面:将通知应用到切入点的过程,是一个动作

通知/增强:实际增强的逻辑部分,自己写的代码部分


·类型:前置通知、后置通知、环绕通知、异常通知、最终通知

·@Before、@AfterReturning、@Around、@AfterThrouing、@After

注:就是定义好切入点、通知,然后利用切面来将通知加入到切入点上。


配置:可以通过切入点表达式@PointCut

代码实现:

  • 引入依赖
  <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.9.4</version>
     </dependency>

1.xml配置实现

<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--配置aop:需要导入aop的命名空间-->
    <aop:config>
        <!--配置切入点 -->
        <aop:pointcut id="point" expression="execution(* dao.*.*(..))"/>
       <!-- 配置通知点,需要log类实现相关的接口-->
        <aop:advisor advice-ref="log" pointcut-ref="point"/>
    </aop:config>
/*
Before(方法执行前) :org.apringframework.aop.MethodBeforeAdvice
AfterReturning(方法返回后) :org.springframework.aop.AfterReturningAdvice
After-throwing(异常抛出后) :org.springframework.aop.ThrowsAdviceArround
环绕,即方法前后 :org.aopaliance.intercept.MethodInterceptor
*/
public class Log implements MethodBeforeAdvice, AfterReturningAdvice,MethodInterceptor  {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("BeforeAdvice方法执行前");
        System.out.println(method.getName()+";"+o.getClass());
    }
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("AfterAdvice方法执行前");
        System.out.println(method.getName()+";"+o.getClass());
    }
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Roundadvice方法执行前");
        System.out.println(methodInvocation.getArguments()[0]);//可以获取目标方法的参数值
        Object result=methodInvocation.proceed();//调用目标对象的方法
        System.out.println("RoundAdvice方法执行完成了");
        return result;
    }
}
  • 2.注解实现
  • xml配置
<!-- JDK(默认proxy-target-class="false") cglib(proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
//定义切面
//定义bean
@Aspect
@Component
public class MyAspect {
    //配置切点,切点的这个方法不需要实现,只是为了给切面的方法作为锚点
    @Pointcut("execution(* testExecution(..))")
    public void anyTestMethod() {}
   //**配置前置通知,使用在anyTestMethod上注册的切入点**很重要!!!
   @Before("ric.study.demo.aop.MyAspect .anyTestMethod()")
    public void doAccessCheck(JoinPoint joinPoint) {
        // ... 实现代码
    }
    // returnVal 就是相应方法的返回值
   // 注意可以通过这样去为你的aop方法获得更多的参数打印详细信息,只要是该注解提供的参数都是这样获取
    @AfterReturning(
        pointcut="ric.study.demo.aop.MyAspect .anyTestMethod()",
        returning="returnVal")
    public void doAccessCheck(Object returnVal) {
        //  ... 实现代码
    }
    // 这种最灵活,既能做 @Before 的事情,也可以做 @AfterReturning 的事情
    @Around("ric.study.demo.aop.MyAspect .anyTestMethod()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        //  target 方法执行前... 实现代码
        Object retVal = pjp.proceed();
        //  target 方法执行后... 实现代码
        return retVal;
    }
}  

https://zhuanlan.zhihu.com/p/127792838


5.spring事务的配置

·1.编程式事务管理编程式事务管理是侵入性事务管理,使用TransactionTemplate或者直接使用PlatformTransactionManager,对于编程式事务管理,Spring推荐使用TransactionTemplate。


·2.声明式事务管理

声明式事务管理建立在AOP之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。


·3.比较

编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现,只需要在配置文件中做相关的事务规则声明或者通过注解的方式,便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是Spring倡导的非侵入式的编程方式。唯一不足的地方就是声明式事务管理的粒度是方法级别,而编程式事务管理是可以到代码块的,但是可以通过提取方法的方式完成声明式事务管理的配置(黑体不懂)

6.spring事务的传播?

事务的传播性一般用在事务嵌套的场景,比如一个事务方法里面调用了另外一个事务方法,那么两个方法是各自作为独立的方法提交还是内层的事务合并到外层的事务一起提交,这就是需要事务传播机制的配置来确定怎么样执行

常用的事务传播机制如下:

  • PROPAGATION_REQUIRED
    Spring默认的传播机制,能满足绝大部分业务需求,如果外层有事务,则当前事务加入到外层事务,一块提交,一块回滚。如果外层没有事务,新建一个事务执行
  • PROPAGATION_REQUES_NEW
  • 该事务传播机制是每次都会新开启一个事务,同时把外层事务挂起,当当前事务执行完毕,恢复上层事务的执行。如果外层没有事务,执行当前新开启的事务即可
  • PROPAGATION_SUPPORT
    如果外层有事务,则加入外层事务,如果外层没有事务,则直接使用非事务方式执行。完全依赖外层的事务
  • PROPAGATION_NOT_SUPPORT
    该传播机制不支持事务,如果外层存在事务则挂起,执行完当前代码,则恢复外层事务,无论是否异常都不会回滚当前的代码
  • PROPAGATION_NEVER
    该传播机制不支持外层事务,即如果外层有事务就抛出异常
  • PROPAGATION_MANDATORY
    与NEVER相反,如果外层没有事务,则抛出异常
  • PROPAGATION_NESTED
    该传播机制的特点是可以保存状态保存点,当前事务回滚到某一个点,从而避免所有的嵌套事务都回滚,即各自回滚各自的,如果子事务没有把异常吃掉,基本还是会引起全部回滚的。

传播规则回答了这样一个问题:一个新的事务应该被启动还是被挂起,或者是一个方法是否应该在事务性上下文中运行


参考链接:

https://www.cnblogs.com/mseddl/p/11577846.html

目录
相关文章
|
16天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
20天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
46 5
|
25天前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
52 8
|
25天前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
24天前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
36 5
|
25天前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
35 4
|
1月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
37 1
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
39 0
|
3月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
73 1
下一篇
DataWorks