Spring常见问题整理(三)

Spring注解

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

@Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用
@Service 而不是 @Component,因为它以更好的方式指定了意图。
@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。

@Import的几种用法

  1. 直接指定类 (如果配置类会按配置类正常解析、 如果是个普通类就会解析成Bean)
  2. 通过ImportSelector 可以一次性注册多个,返回一个string[] 每一个值就是类的完整类路径
  3. 通过DeferredImportSelector可以一次性注册多个,返回一个string[] 每一个值就是类的完整类路径
    区别:DeferredImportSelector 顺序靠后
  4. 通过ImportBeanDefinitionRegistrar 可以一次性注册多个,通过BeanDefinitionRegistry来动态注册BeanDefintion

如何让自动注入没有找到依赖Bean时不报错

这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required
注解的bean属性未被设置,容器将抛出BeanInitializationException。示例:

@Autowired(required = false) 
private Role role;

@Autowired 注解

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。

@Autowired和@Resource之间的区别

@Autowired可用于:构造函数、成员变量、Setter方法
@Autowired和@Resource之间的区别:

  1. @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为 false)。
  2. @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
使用@Autowired注解自动装配的过程

@Autowired 通过Bean的后置处理器进行解析的

  1. 在创建一个Spring上下文的时候再构造函数中进行注册AutowiredAnnotationBeanPostProcessor
  2. 在Bean的创建过程中进行解析
    1.在实例化后预解析(解析@Autowired标注的属性、方法 比如:把属性的类型、名称、属性所在的类… 元数据缓存起)
    2.在属性注入真正的解析(拿到上一步缓存的元数据 去ioc容器帮进行查找,并且返回注入)
    1)首先根据预解析的元数据拿到 类型去容器中进行查找
    如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
    如果查询的结果不止一个,那么@Autowired会根据名称来查找;
    如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。

配置类@Configuration的作用解析原理

  1. @Configuration用来代替xml配置方式spring.xml配置文件 <bean>
  2. 没有@Configuration也是可以配置@Bean
  3. @Configuration加与不加有什么区别?
    加了@Configuration会为配置类创建cglib动态代理(保证配置类@Bean方法调用Bean的单例),@Bean方法的调用就会通过容器.getBean进行获取。
    原理:
    1.创建Spring上下文的时候会注册一个解析配置的处理器ConfigurationClassPostProcessor(实现 BeanFactoryPostProcessor和 BeanDefinitionRegistryPostProcessor)
    2.在调用invokeBeanFactoryPostProcessor,就会去调用
    ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry进行解析配置(解析配置类说白就是去解析各种注解@Bean @Configuration@Import @Component … 就是注册BeanDefinition)
    3.ConfigurationClassPostProcessor.postProcessBeanFactory去创建cglib动态代理

Spring AOP

AOP(Aspect-Oriented Programming),一般称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。
AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。 而AOP作为面向对象的一种补充,则是针对业务处理过程中的切面进行提取,已达到业务代码和公共行为代码之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

Spring AOP里面的几个名词解释

(1)切面(Aspect): 在Spring Aop指定就是“切面类” ,切面类会管理着切点、通知。
(2)连接点(Join point): 指定就是被增强的业务方法
(3)通知(Advice): 就是需要增加到业务方法中的公共代码, 通知有很多种类型分别可以在需要增加的业务方法,不同位置进行执行(前置通知、后置通知、异常通知、返回通知、环绕通知)
(4)切点(Pointcut): 由他决定哪些方法需要增强、哪些不需要增强,结合切点表达式进行实现
(5)目标对象(Target Object): 指定是增强的对象
(6)织入(Weaving) : spring aop用的织入方式:动态代理,就是为目标对象创建动态代理的过程就叫织入

Spring通知类型

  1. 前置通知(Before):在目标方法被调用之前调用通知功能;
  2. 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  3. 返回通知(After-returning ):在目标方法成功执行之后调用通知;
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  5. 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
    执行顺序:
    1、正常执行:@Before­­­->方法­­­­->@AfterReturning(返回)-­­­>@After
    2、异常执行:@Before-­­­>方法­­­­->@AfterThrowing­­­(异常)->@After

AOP的有几种实现方式

  • Spring 1.2 基于接口的配置:最早的 Spring AOP 是完全基于几个接口的,想看源码的同学可以从这里起步。
  • Spring 2.0 schema-based 配置:Spring 2.0 以后使用 XML 的方式来配置,使用 命名空间
  • Spring 2.0 @AspectJ 配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫做 @AspectJ,但是这个和 AspectJ 其实没啥关系。
  • AspectJ 方式,这种方式其实和Spring没有关系,采用AspectJ 进行动态织入的方式实现AOP,需要用AspectJ 单独编译。

什么情况下AOP会失效,怎么解决

失效原因:

  1. 方法是private 也会失效,解决:改成public
  2. 目标类没有配置为Bean也会失效, 解决:配置为Bean
  3. 切点表达式没有配置正确
    解决方式:必须走代理, 重新拿到代理对象再次执行方法才能进行增强
  4. 在本类中自动注入当前的bean
  5. 设置暴露当前代理对象到本地线程, 可以通过AopContext.currentProxy() 拿到当前正在调用的动态代理对象
@EnableAspectJAutoProxy(exposeProxy = true)

Spring的 Aop的完整实现流程

Aop的实现大致分为三大步:JavaConfig
当@EnableAspectJAutoProxy 会通过@Import注册一个BeanPostProcessor处理AOP
1.解析切面: 在Bean创建之前的第一个Bean后置处理器会去解析切面(解析切面中通知、切点,一个通知就会解析成一个advisor(通知、切点))
2.创建动态代理 正常的Bean初始化后调用BeanPostProcessor 拿到之前缓存的advisor ,再通过advisor中pointcut ,判断当前Bean是否被切点表达式匹配,如果匹配,就会为Bean创建动态代理(创建方式1.jdk动态代理2.cglib)。
3.调用:拿到动态代理对象, 调用方法 就会判断当前方法是否增强的方法,就会通过调用链的方式依次去执行通知.

参考视频链接:

https://www.bilibili.com/video/BV15Q4y1m78a?p=46

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值