Spring 学习笔记

视频链接

BeanDefinition

BeanDefinition用来表示Bean定义。
Spring根据BeanDefinition来创造对象。
BeanDefinition中重要的属性

  1. beanClass
    表示bean类型 如UserService.class,OrderService.class
    Spring在创建Bean的过程中会根据此属性来实例化得到对象
  2. scope
    bean的作用域
    如singleton,单例Bean;prototype,原型Bean.
  3. isLazy
    表示bean是否需要懒加载,原型Bean的isLazy属性不起作用
    懒加载的bean会在第一次getBean生成
    非懒加载的bean在spring启动时就会生成
  4. dependsOn
    该bean创建前所以来的其他bean,该bean创建前,他依赖的bean要创建好
  5. primary
    表示该bean是个主bean。在spring中同一个类型可能有多个bean对象,在进行依赖注入时会判断是否有主bean,如果有则直接注入
  6. initMethodName
    表示一个bean的初始化方法,bean生命周期有个步骤是初始化,Spring会在这个过程中去调用bean的初始化方法,程序员可以自定义逻辑对bean进行初始化。

@Component,@Bean, <bean/>都会解析为BeanDefinition对象。

BeanFactory

一种“spring容器”,用来创建bean,获取bean
BeanFactory利用Beandefinition来生成Bean对象。

核心子接口和实现类:

ListableBeanFactory
ConfigurationBeanFactory
AutowiredCapableBeanFactory
AbstractBeanFactory
DefaultListableBeanFactory:支持单例Bean,Bean别名,父Beanfactory,Bean类型转化,Bean后置处理,FactoryBean,自动装配等等

Bean生命周期

Spring中创建到销毁一个Bean的过程。创建是重点。程序员可以利用Bean生命周期对Bean进行加工。

核心步骤

  1. BeanDefinition对象创建
  2. 构造方法推断-选出一个构造方法
  3. 实例化-构造方法反射得到对象
    在Spring中,可以通过BeanPostProcessor机制对实例化进行干预
  4. 属性填充-属性自动填充
    实例化得到的对象中的某些属性还没进行属性填充,属性填充就是自动注入,依赖注入。
  5. 初始化-对其他属性赋值,校验
    程序员可以利用初始化机制对Bean进行自定义加工,比如利用InItializingBean接口来对Bean中的其他属性进行赋值,或者对Bean中的某些属性进行校验。
  6. 初始化后-AOP,生成代理对象
    AOP机制就是在这个步骤中通过BeanPostProcessor机制实现的,初始化后的得到的对象才是真正的Bean对象。

@Autowired

表示某个属性是否需要依赖注入,可以写在属性和方法上。注解中的required属性默认为True,表示如果没有对象注入给属性则抛异常。
写在属性上,Spring在bean的生命周期中的属性填充时,会基于实例化出来的对象,对该对象中加了Autowired的属性自动给属性赋值。
Spring会吸纳根据属性的类型去Spring容器中找出该类型所有的bean对象,找出多个,再根据属性名字确定。如果required为true,并且根据属性信息找不到对象,则直接抛异常。
写在方法上,Spring在bean的生命周期中的属性填充时,会根据方法的参数类型,参数名字从Spring容器中找到对象当做方法入参,自动反射调用该方法。
加载构造方法上,Spring会在推断构造方法阶段,选择该构造方法进行实例化,在反射调用构造方法之前,会先根据构造方法参数类型,参数名从Spring容器中找到Bean对象,当做构造方法入参。

@Resource

和@Autowired类似,也是进行依赖注入的。@Resource是java层面提供的注解,@Autowired是Srping提供的注解,依赖注入的底层实现逻辑也不同。
@Resource中有个name属性,针对name是否有值,@Resource的依赖注入底层流程不同的。
如果有值,那么Spring会根据name直接去Spring容器中寻找Bean对象,如果找到则成功,否则报错。
如果没有值,判断属性名字在Spring容器中是否有bean对象,如果有则成功注入。如果不存在则根据属性类型去Spring容器中找Bean对象,找到一个则进行注入。

@Value

也是进行依赖注入的,只不过@Value从properties文件中取值,并且@Value可以解析SpringEL表达式
@Value(“zhouyu”) 直接将zhouyu赋值给属性,如果属性类型不是String,或者无法进行类型转换,则报错。
@Value(“${zhouyu}”)会把 ${}中字符串当做key去properties文件中找出对应value赋值给属性,如果没找到,则会把“”中当做普通字符串注入给属性。
@Value(“#{zhouyu}”)会把字符串当做Spring表达式来进行解析 Spring会把zhouyu当做beanName,并从Spring容器中找到对应的bean,如果找到则进行属性注入,没找到则报错。

FactoryBean

Spring所提供的一种比较灵活的创建bean的方式,可以通过实现FactoryBean接口中的getObject()方法来返回一个对象,这个对象就是最终的bean对象。
FactoryBean是一个bean对象,也是一个小型工厂,可以生产出其他的bean
beanFactory是一个Spring容器,是一个大工厂,能生产出各种各样的其他bean
factoryBean被广泛应用于Spring内部和与第三方整合的过程中。

ApplicationContext

AppliactionContex是比beanFactory更加强大的Spring容器,它既可以创建bean,获取bean还支持国际化,时间广播,获取资源等beanFactory不具备的功能。
继承的接口有

  • EnvironmentCapable
    拥有获取环境变量的功能,可以通过applicationContext获取操作系统变量和JVM环境变量。
  • ListableBeanFactory
    拥有获取所有beanNames,判断某个BeanName是否存在beanDefinition对象,统计beanDefinition个数,获取某个类型对应的所有beanNames等功能。
  • HierarchicalBeanFactory
    获取父BeanFactory,判断某个name是否存在bean对象的功能
  • MessageSource
    拥有了国际化功能,比如利用MessageSource对象获取某个国际化资源(比如不通国家语言所对应的字符 )
  • ApplicationEventPublisher
    事件发布功能
  • ResourcePatternResolver
    拥有加载并获取资源的功能,这里的资源可以是文件,图片等某个URL资源都可以。

BeanPostProcessor

Spring提供的扩展机制,可以利用该机制对Bean进行定制化加工,在Spring底层源码实现中,也广泛用到了该机制,BeanPostProcessor通常叫做Bean后置处理器。
BeanPostProcessor是一个接口,我们定制一个后置处理器,就是提供一个类来实现该接口。在spring中存在其他类继承该接口,这些子接口在beanpostprocessor的基础上增加了一些其他的功能。
postProcessbeforeInitialiation
初始化前方法,表示可以利用这个方法来对Bean在初始化前进行自定义加工。
postProcessAfterInitialiation
Bean初始化后进行自定义加工。
instantiationAwareBeanPostPorcessor
BeanPostProcessor的一个接口,
postProcessorBeforeInstantiation()实例化前
postProcessorAfterInstantiation()实例化后
postProcessorProperties()属性注入后

Aop面向切面编程

适合在不修改业务代码的前提下,对某个或者某些业务增加统一的功能,比如日志记录,权限控制,事务管理等,能很好地使得代码解耦,提高开发效率

  • Advice
    通知,建议。在spring中通过定义advice来定义代理逻辑
  • Pointcut
    切点。表示advice的代理逻辑应用在哪个类哪个方法上。
  • Advisor
    =advice+pointcut。表示代理逻辑和切点的一个整体。程序员可以通过定义或封装一个Advisor,来定义切点和代理逻辑。
  • Weaving
    织入。将advice代理逻辑在源代码级别嵌入切点的过程叫做织入。
    -Target
    被代理对象。在aop生成的代理对象中会持有目标对象。
  • JointPoint
    表示连接点。在spring aop中就是方法的执行点。

工作原理

aop发生在bean的生命周期过程中的:
1.spring生成bean对象过程中,会先实例化出来一个对象,也就是target对象
2.在对target对象进行属性填充
3.在初始化后步骤中,会判断target对象有没有对应的切面
4.如果有切面,就表示当前对象需要进行aop
5.通过cglib或者jdk动态生成代理对象,作为最终的bean对象
6.代理对象中有一个target属性指向了target对象

javaBean,SpringBean和对象区别

bean肯定是对象
对象 User user =new User();
javaBean user中属性都是私有,对外提供getter和setter。
spring Bean spring生成的对象。
在这里插入图片描述

定义bean

1.xml定义 <bean></bean> ClassPathXmlApplicationContext 基于类中构造方法生成对象
在这里插入图片描述

2.类定义@Bean AnnotationConfigApplicationContext new出来的
在这里插入图片描述
3.@Component

以上是声明式的
4.编程式的BeanDefinition
在这里插入图片描述

标签、注解、component、BeanDefinition
5. FactoryBean
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
6.supplier
在这里插入图片描述

单例池,单例Bean,单例模式的区别

User 单例Bean==spring容器中只能有一个User类型的bean (×)
单例池,存储单例bean,实现单例bean功能 ConcurrentHashMap stringObject beanName object
非懒加载的单例Bean spring启动时创建好

BeanFactory, ApplicationContext

BeanFactory容器 Beandefinition/对象
BeanFactory继承单例池。

ApplicaitonContext继承 xxxBeanFactory
多了国际化,发布时间,获取环境等方法。

applicationContext常见实现类:applicationConfigApplicationContext,ClassPathXmlApplication,FileSystemXmlApplicaitonContext。
1.可不可以刷新2.spring配置的展现形式
ClassPathXmlApplication 相对于classpath (可刷新)
FileSystemXmlApplicaitonContext 相对于项目工程,也支持绝对路径
在这里插入图片描述
AnnotationConfigApplicationContext(不可刷新)
在这里插入图片描述

在这里插入图片描述
刷新相当于重启。重新加载容器,可以修改。看是否继承
在这里插入图片描述

Bean的生命周期

创建生命周期,销毁生命周期
在这里插入图片描述

实例化

beanPostProcess 在实例化对象后进行处理,可以类似实现autowired
在这里插入图片描述
可以设置指定被代理对象。

实例化前

实现instantiationAwareBeanPostProcessor
重写postProcessBeforeInstantiation
实现实例化前的操作

推断构造方法

  • 多个构造方法,spring无法判断时,会先调用无参的构造方法。
  • 可以用autowired来指定。
  • @Autowired(required=false)时,优先匹配多个参数的构造方法。
  • 参数个数相同,且都能匹配到,按照顺序来。

实例化后

实现instantiationAwareBeanPostProcessor
重写postProcessAfterInstantiation return false时,不再走spring的逻辑

初始化

实现InitializingBean接口
重写afterPropertiesSet方法
@PostConstruct 属性注入后,初始化前 针对bean

初始化前

实现BeanPostProcessor接口
重写postProcessorBeforeInitialization

  • 返回null不会执行其他的初始化前方法
  • 返回bean会接续执行

初始化后

重写postProcessorAfterInitialization
可以在此进行aop
Proxy.newProxyInstance(类加载器,类实现的接口,new InvocationHandler{
@Override
public Object invoke(Object proxy,Method method,object[] args){
sout 代理逻辑
method.invoke(bean,args);
}
});
在这里插入图片描述
autowired 先类型匹配再进行名称匹配。
单例bean 根据同一个名字拿,拿到的是同一个bean
原型,多例,不是同一个
单例池,实现单例bean Map存储
spring 定义bean,还得能加载到才能使用。
编程式:有了beandefinition还得registerBeanDenifition 定义对象需要有构造方法(不能是接口)
声明式:有了@Component还得@ComponentScan(“包路径”)

在这里插入图片描述

在这里插入图片描述
idea 点击属性时,调用的是属性的toString方法

MyBatis

在这里插入图片描述
创建后调用方法,会找不到userMapper类

@Mapper到springboot才用到
userMapper接口,需要存储在spring容器中。
可以是实现类或者代理对象,代理对象由mybatis产生,将代理对象放入spring容器中成为springbean
spring事务

  • 声明式 @Transan
  • 编程式 TransManager创建
    srping 定义Bean
  • 声明式
<Bean/> @BEAN	@Component

需要添加扫描才能添加到

  • 编程式 beanDefinition
    在这里插入图片描述

beanDefinition创建对象,设置BeanClass后,调用registerBeanDefinition添加到spring 容器中
接口不可以这样,因为创建bean时,会进行实例化,接口,没有构造方法会实例化失败
新建类实现FactoryBean
在这里插入图片描述
定义一个类返回两个对象,注册时xxx为person,&xxx为源对象
在这里插入图片描述
其中persion变为了spring对象,因此在该类中getObject方法中放入mapper接口的代理对象。
proxy.newProxyInstance(classLoader(这里使用当前类的),被代理接口,newInvocationHandler){}
null不报空指针是因为toString

最后通过替换FactoryBean实现类中的class,私有属性,新建构造方法传入类,即可复用。

beanDefinition.getConstructArgumentValues(). addGenericArgumentvalue();
在这里插入图片描述
注册代理对象类代码优化
新建类继承 importBeanDefinitionRegistarar
在spring启动类上添加注解@Import(LubanImportBeanDefinitionRegistarar)
在这里插入图片描述
重写方法,利用spring扫描逻辑进行复制和注册到spring容器中。
在这之前新建类继承ClassPathBeanDefinitionScanner
在这里插入图片描述

在这里插入图片描述
使用sqlsession获取代理对象。
在这里插入图片描述
动态获取路径,手写注解,value值,将import(创建bean的类)放入新写的注解上,利用registerBeanDefinition方法中的AnnotionMetadata
importClassMetadata来获取注解参数来获取path。

循环依赖

java类中相互依赖没有问题。但是在spring中根据bean的生命周期会出现问题。
例如A和B相互依赖
springBean的生命周期:实例化,自动填充,aop,放入单例池。
在自动填充时,他们会寻找依赖的bean,现在单例池中找,然后去spring容器中找,都找不到就回去创建,而相互依赖会导致这个过程一直反复。
解决方法:新增map进行缓存,在生命周期实例化时,将新建但未赋值的对象放入map中。
在这里插入图片描述
新建A对象,对a对象中的b对象赋值,发现没有b对象,于是创建b对象,在b对象中对a对象赋值,a对象虽然为未赋值的实例化对象,但是最后在给a中的属性赋值,也就是图中的a.b=b。
在循环依赖的过程中,生命周期有其他属性赋值,因此缓存并不会产生问题。

赋值需要代理对象,否则无法调用方法。产生新问题:提前进行aop
在这里插入图片描述直接将代理对象放入map中。

判断是否有循环依赖,并且有切面,才会提前aop。
在2.2部判断是否有循环依赖,

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
还在写

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小明和大树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值