面试必会系列 – 1.8 Spring IOC / AOP原理

面试必会系列 – 1.8 Spring IOC / AOP原理Spring原理概览IOCAOPIOCSpringIOC常用注解使用注解的方式将bean注册到IOC容器中这四个注解写在类上面的时候,都可以完成注册bean的功能,但是这些规定并不是spring识别的依据在spring运行过程中,不会对这4个注解做任何区分,看起来都是一样的,都会完成bean的注册功能在实际开发中,最好能分清楚,提高代码的可读性@Component组件,理论上可以在任何位置添加,在扫描的时候都会完成bean的注册。最偷懒的方式,就是给所有需要注

大家好,又见面了,我是你们的朋友全栈君。

本文已收录至 Github(MD-Notes),若博客中图片模糊或打不开,可以来我的 Github 仓库,包含了完整图文https://github.com/HanquanHq/MD-Notes,涵盖了互联网大厂面试必问的知识点,讲解透彻,长期更新中,欢迎一起学习探讨 ~

更多内容,可以访问:

面试必会系列专栏https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系统系列专栏https://blog.csdn.net/sinat_42483341/category_10519484.html



Spring 原理

概览

  • IOC
  • AOP

IOC

Spring IOC 常用注解

使用注解的方式将 bean 注册到 IOC 容器中

这四个注解写在类上面的时候,都可以完成注册bean 的功能,但是这些规定并不是spring识别的依据

在spring运行过程中,不会对这4个注解做任何区分,看起来都是一样的,都会完成bean的注册功能

在实际开发中,最好能分清楚,提高代码的可读性

@Component

组件,理论上可以在任何位置添加,在扫描的时候都会完成 bean 的注册。最偷懒的方式,就是给所有需要注册的 bean 上面添加 @Component 注解

@Controller

放在控制层,用来接收用户的请求

@Service

放在业务逻辑层

@Repository

放在 dao 数据访问层

@ComponentScan

Spring容器在运行的时候,怎么知道从哪个包扫描呢?

所以,在使用上述注解的时候,需要 xml 文件中配置context:conponent-scan,并且导入 context 命名空间

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonController personController = context.getBean("personController", PersonController.class)
使用注解的时候,并没有定义 bean 的 id 和 class,那么 spring 是怎么识别的呢?

是把当前类的名称首字母小写来识别的。需要的话,你可以在注解中使用value=修改名称,一般不会去修改。

使用 @Autowired 进行自动注入

首先,bean 已经被注册到Spring IOC 容器中了,但是如果不使用 Autowired 的话,没有被注入到对象中。

@AutoWired 是通过反射的方式注入的。

Autowired 是根据什么依据来装配的呢?by name?by type?

当使用AutoWired注解的时候,自动装配的时候是根据类型实现的。

  1. 如果只找到一个,则直接进行赋值,
  2. 如果没有找到,则直接抛出异常,
  3. 如果找到多个,那么会按照变量名作为id继续匹配,
    1. 匹配上直接进行装配
    2. 如果匹配不上则直接报异常

还可以使用@Qualifier注解来指定id的名称,让spring不要使用变量名,当使用@Qualifier注解的时候也会有两种情况:

  1. 找到,则直接装配
  2. 找不到,就会报错
@AutoWired可以进行定义在方法上
@Controller
public class PersonController { 
   
     /** * 当方法上有@AutoWired注解时: * 1、此方法在bean创建的时候会自动调用 * 2、这个方法的每一个参数都会自动注入值 * @param personDao */
    @Autowired
    public void test(PersonDao personDao){ 
   
        System.out.println("此方法被调用:"+personDao);
    }

自动装配的注解@AutoWired,@Resource 区别

在使用自动装配的时候,出了可以使用@AutoWired注解之外,还可以使用@Resource注解,你需要知道这两个注解的区别。

  1. @AutoWired:是spring中提供的注解,

    @Resource:是jdk中定义的注解,依靠的是java的标准

  2. @AutoWired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在

    @Resource默认是按照名字进行匹配的,同时可以指定name属性

  3. @AutoWired只适合spring框架,而@Resource扩展性更好

IOC 原理

为什么有 IOC 容器?它的好处是什么?

当我们需要获取对象的时候,可以创建一个工厂类,让工厂类帮我们创建对象。能不能把这个过程让别人来做?
我们只需要知道容器里有对象,我们只要拿来用就好了。至于谁创建的,什么时候创建的,这都不需要你操心。
这时候你会想,假设有一个管理器,给你分配 bean,并且可以满足你的个性化需求,这样就好了。于是,我们有了 IOC 容器。

IOC 容器,是使用 Map 存放对象的地方,对象是通过反射创建的。默认情况下,对象在 IOC 容器中都是单例的。如果需要多例,可以修改属性。

IOC 和 DI 的关系?

IOC 是控制翻转,DI 是依赖注入。
IOC 和 DI 是从不同的角度描述同一件事情,IOC 是从容器的角度考虑的,而 DI 是从应用程序的角度考虑的。
IOC 只是一种思想,而 DI 才是具体的实现方式。

什么是控制翻转?

有了 IOC 之后,依赖的对象直接由 IOC 容器创建后,注入到对象中。
由我们主动创建,变成了被动接受,这就是控制反转。

bean 对象信息读取

但是,容器怎么知道你需要什么对象呢?你需要告诉容器,比如通过配置 xml 文件,比如使用注解。BeanDefiniton 就是用来定义类的信息的,你把信息传输给容器,容器接收到信息之后,才能创建对应的对象。
在程序启动的时候,需要把这些定义信息读取进来。但是,有的人用 xml,有的人用注解,怎么统一呢?
这时候,定义一 个 BeanDefinitonReader,用来读取 Bean 的定义信息,如果以后有了新的方式定义 Bean 信息,只需要实现当前接口,就可以了。BeanDefinitonReader 是一个接口,下面有很多不同的实现类,就是很多不同的读取方式。

在这里插入图片描述

创建对象

拿到对象信息之后,需要进行实例化操作。我们知道,创建对象可以通过 new / 工厂/ 反射 的方式实现。实际上,Spring 是通过反射的方式创建对象的。BeanFactory 工厂,可以用来生产对象、访问工厂。

// bean 实例化,只是一个空对象,没有任何属性值
Constructor constructor = TestClass.class.getConstructor();
Object o = constructor.newInstance();

实例化对象

BeanProcessor 里面有 Before / AfterInitialization

在这里插入图片描述

AOP

AOP简介

面向切面编程,AOP是OOP的补充,当我们需要为多个对象引入一个公共行为,比如日志,操作记录等,就需要在每个对象中引用公共行为,这样程序就产生了大量的重复代码,使用AOP可以完美解决这个问题。

AOP 实现机制:动态代理

动态代理和静态代理的区别是,静态代理的的代理类是我们自己定义好的,在程序运行之前就已经变异完成,但是动态代理的代理类是在程序运行时创建的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

  • cglib
  • jdk

如何实现一个 AOP

AOP:【动态代理】
          指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
  
  1、导入aop模块;Spring AOP:(spring-aspects)
  2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
  3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
          通知方法:
              前置通知(@Before):logStart:在目标方法(div)运行之前运行
              后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
              返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
              异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
              环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced()4、给切面类的目标方法标注何时何地运行(通知注解);
  5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
  6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
  7、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
          在Spring中很多的 @EnableXXX;
  
  三步:
      1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
      3)、开启基于注解的aop模式;@EnableAspectJAutoProxy
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148147.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm 激活码Key is invalid(JetBrains全家桶)

    (pycharm 激活码Key is invalid)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1STL5S9V8F-eyJsaWNlbnNlSWQiOi…

    2022年3月27日
    1.1K
  • 数据结构算法常见面试考题及答案_数据结构和算法面试题

    数据结构算法常见面试考题及答案_数据结构和算法面试题(1)红黑树的了解(平衡树,二叉搜索树),使用场景把数据结构上几种树集中的讨论一下:1.AVLtree定义:最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(logn)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。…

    2022年9月29日
    0
  • bytebuf详解_byte int

    bytebuf详解_byte int@author鲁伟林记录《Netty实战》中各章节学习过程,写下一些自己的思考和总结,帮助使用Netty框架的开发技术人员们,能够有所得,避免踩坑。本博客目录结构将严格按照书本《Netty实战》,省略与Netty无关的内容,可能出现跳小章节。本博客中涉及的完整代码:GitHub地址:https://github.com/thinkingfioa/netty-learning/tre…

    2022年9月19日
    0
  • 数据库隔离级别—MySQL的默认隔离级别就是Repeatable,Oracle默认Read committed,最高级别Serializable

    数据库隔离级别—MySQL的默认隔离级别就是Repeatable,Oracle默认Read committed,最高级别Serializable数据库隔离级别—MySQL的默认隔离级别就是Repeatable,Oracle默认Readcommitted,最高级别Serializable

    2022年5月9日
    93
  • RJ45 网线接口介绍

    RJ45接口通常用于数据传输,最常见的应用为网卡接口。  RJ45是各种不同接头的一种类型(例如:RJ11也是接头的一种类型,不过它是电话上用的);RJ45头根据线的排序不同,分为有两种,一种是橙白、橙、绿白、蓝、蓝白、绿、棕白、棕;另一种是绿白、绿、橙白、蓝、蓝白、橙、棕白、棕;因此使用RJ45接头的线也有两种即:直通线、交叉线。RJ45型网卡接口  10100basetxRJ

    2022年4月9日
    50
  • 无源汇上下界可行流_有源点和无源点的区别

    无源汇上下界可行流_有源点和无源点的区别给定一个包含 n 个点 m 条边的有向图,每条边都有一个流量下界和流量上界。给定源点 S 和汇点 T,求源点到汇点的最小流。输入格式第一行包含四个整数 n,m,S,T。接下来 m 行,每行包含四个整数 a,b,c,d 表示点 a 和 b 之间存在一条有向边,该边的流量下界为 c,流量上界为 d。点编号从 1 到 n。输出格式输出一个整数表示最小流。如果无解,则输出 No Solution。数据范围1≤n≤50003,1≤m≤125003,1≤a,b≤n,0≤c≤d≤21474836

    2022年8月11日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号