当前位置:网站首页 > Java基础 > 正文

java spring菜鸟教程(java spring 教程)



@Configuration

之前使用bean.xml配置spring相关配置读取配置的时候

 
  

使用注解的时候我们使用配置类来配置spring的相关配置,读取配置如下

 
  

配置类中我们配置对应的@Bean注解来把对应的类放到容器中,这样我们就可以通过对应的名称来获取容器中的对象了。

 
  

@ComponentScan

这是一个扫描包的注解,配置对应的value属性可以扫描指定包下的所有类,然后把使用了对应注解的类添加到容器中。

 
  

其中过滤器有多种属性

 
  

使用自定义的过滤器,返回true证明扫到的类可用,false表示不可用

 
  

@Scope注解

 
  

@Lazy

 
  

@Conditional

 
  

对应的WindowsCondition.class,linxu差不多

 
  

@import

用来向容器中导入类的注解有以下的三种使用方法:

 
  

第一种使用方法:直接import 类的class对象

 
  

第二种使用方法:使用importselect来导入

 
  
 
  

第三种:使用使用ImportBeanDefinitionRegistrar

 
  
 
  

第四种注入bean方法

配置

使用FactoryBean进行容器的注入

1)、默认获取到的是工厂bean调用getObject创建的对象

2)、要获取工程bean本身,我们需要使在默认名称之前加上&,这个是默认的规定

 
  

ColorFactoryBean类

 
  

之后我们可以看到容器中有了一个叫做colorFactoryBean的对象。我们获取这个对象可以看到这个对象的属性是class com.atguigu.bean.Color

Bean的生命周期

 
  
1)、使用@Bean的注解
 
  
 
  
2)、继承接口
 
  
 
  
3)、JSR250注解
 
  
4)、初始化的前后通知

把继承的类当做组件添加到容器后生效。会在执行实例的初始化方法前后执行对应的操作

 
  
一些源码
 
  

Spring底层对BeanPostProcess的使用

一堆后置处理器,可以完成很多功能的实现

@Value

可以自动配置属性的值,有三种不同的值配置方式

  • 使用基本数值,字符串,int之类的
  • 写SpEL表达式:#{}里面可以进行一些简单的运算操作
  • 使用${},从环境中获取对应的数据
 
  

其中使用${}的时候需要注意,需要先把对应的配置文件导入才可以进行自动配置。在xml文件中导入的办法

 
  

在配置文件中导入的方法需要使用@PropertiesSource 来实现,他是一个可以重复使用的注解,可以配置多个

 
  
 
  

@PropertiesSource

如上所示,用来获取配置文件的一个注解

当我们把配置放到了环境中。可以通过注解获取到也可以通过环境来获取到对应的注解属性

 
  

@Autowired

 
  

以下为个人理解

使用@Autowired自动注入的时候,会先去容器中按照类型获取对应的类,来注入到对应的位置。

image-20210412183847870.png

但是如果存在多个相同类型的bean那么就会根据一定的规则来选择bean

image-20210412184245680.png

如果我们想要自己控制注入的类型的id使用@Qualifier来完成,

image-20210412184406389.png

使用@Primary可以告诉容器这个bean是优先级比较高的一个。优先使用带有@Primary的。使用之后也可以使用@Qualifier,但是@Qualifier优先级比@Primary高

@Autowired可以标注的位置

image-20210412194739177.png

  • 标注在方法位置:
    • 可以标注在普通类的普通方法上,这样如果方法有参数,参数在容器中存在就会自动注入
    • 普遍使用是和@Bean使用,被bean注解的方法,如果有参数,会自动从容器中寻找对应的方法,而且不用写@Autowired注解
  • 标注在构造方法上:
    • 如果组件只有一个构造方法,那么这个有参构造方法可以不写@Autowired会自动从容器中获取。
    • 如果有多个的话,和普通方法一样,会自动从容器中找到对应的类型注入
  • 放在参数位置上
    • 字面意思。无需多言

@Resource和其他的自动注入类

 
  

在bean中获取底层组件

 
  

Aware.png

 
  

@Profile

spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能

开发环境,测试环境,生产环境

数据源:(/A)(/B)(/C);

 
  
示例一:使用虚拟机配置启动环境
 
  

image-20210412213542304.png

启动之后发现只有对应的环境下的数据源可以被获取到

示例二:配置激活环境
 
  

使用

 
  

原理

AOP原理:@EnableAspectJAutoProxy入手

流程:

1、创建IOC容器

2、注册配置类,然后调用refresh方法。刷新容器

image-20210414162716019.png

3、refresh刷新,注册的bean的后置处理器来拦截bean创建:

image-20210414162759975.png

3.1先获取IOC容器已经定义的需要创建对象的所有BeanPost

1.@EnableAspectJAutoProxy

  • @EnableAspectJAutoProxy 通过@Import(AspectJAutoProxyRegistrar.class)给spring容器中导入了一个AnnotationAwareAspectJAutoProxyCreator。
  • AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor。它可以拦截spring的Bean初始化(Initialization)前后和实例化(Initialization)前后。
  1. AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation(bean实例化前):会通过调用isInfrastructureClass(beanClass)来判断 被拦截的类是否是基础类型的Advice、PointCut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect),若是则放入adviseBean集合。这里主要是用来处理我们的切面类。
  2. AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessorsAfterInitialization(bean初始化后):
    1. 首先找到被拦截的Bean的匹配的增强器(通知方法),这里有切入点表达式匹配的逻辑
    2. 将增强器保存到proxyFactory中,
    3. 根据被拦截的Bean是否实现了接口,spring自动决定使用JdkDynamicAopProxy还是ObjenesisCglibAopProxy
    4. 最后返回被拦截的Bean的代理对象,注册到spring容器中
  3. 代理Bean的目标方法执行过程:CglibAopProxy.intercept();
    1. 保存所有的增强器,并处理转换为一个拦截器链
    2. 如果没有拦截器链,就直接执行目标方法
    3. 如果有拦截器链,就将目标方法,拦截器链等信息传入并创建CglibMethodInvocation对象,并调用proceed()方法获取返回值。proceed方法内部会依次执行拦截器链。

1、使用

1.导入相关依赖

数据源,数据库驱动,spring-jdbc模块

2.配置数据源。。JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据

3.给方法上标注@Transactional表示当前方法是一个事务方法

4.@EnableTransactionManagement开启基于注解的事务管理功能

5.配置事务管理器来控制事务

 
  
 
  
 
  
 
  

2、原理

@EnableTransactionManagement上有一个注解会给容器导入一个TransactionManagementConfigurationSelector对象,来进行一些组件的导入

 
  

TransactionManagementConfigurationSelector源码如下:

 
  

实导入两个组件

AutoProxyRegistrar.class

ProxyTransactionManagementConfiguration.class

AutoProxyRegistrar干什么的

继承了注册bean的接口,给容器中注册了一个InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator是做什么的:
利用后置处理器机制在对象创建一后,包装对象,返回一个代理器对象,代理对象执行方法利用拦截器执行对象。

ProxyTransactionManagementConfiguratio干什么的

给容器中利用bean注册各种组件:

  • 事务增强器:
    • 事务注解器:要用事务注解的信息AnnotationTransactionAttributeSour接卸事务的注解
    • 事务拦截器:TransactionInterceptor保存了事务属性信息,事务管理器。他是一个MethodInterceptor方法拦截器。在目标方法执行的时候执行拦截器链。
      • 事务拦截器功能
        • 先获取事务属性,再去获取PlatformTransactionManager
        • 如果出现异常获取事务,回滚,没有异常获取事务提交

image-20210415155724554.png

1.BeanFactoryPostProcessor

  • BeanPostProcessor是Bean后置处理器:bean创建初始化前后进行拦截工作
  • BeanFactoryPostProcessor是Bean工厂后置处理器:
    • 在BeaanFactory标准初始化之后进行调用:所有bean定义已经保存加载到beanFactory,但是Bean的实例还没有创建

1)、IOC容器创建对象

2)、invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessors

  • 如何找到所有的BeanFactoryPostProcessor并执行它们的方法
    • 1)、直接在BeanFactory中找到所有类型是BeanFactoryPostProcess的组件,并执行它们的方法。
    • 2)、在初始化其他组件前面执行。

2.BeanDefinitionRegistryPostProcessor

 
  

执行方法:postProcessBeanDefinitionRegistry

在所有Bean定义信息将要被加载,bean实例还没有被创建的时候。

这里类的执行顺序比BeanFactoryPostProcessor执行的早,并且可以在这个类中注册bean信息。给容器中添加一些组件。

原理:

  • 1、IOC创建对象
  • 2、调用刷新方法()-》invokeBeanFactoryPostProcessors(beanFactory);
  • 3、先从容器中获取到所有的BeanDefinitionRegistrayPostProcessor组件。
    • 依次除法所有的postProcessBeanDefinitionRegistry()方法
    • 之后再触发postProcessBeanFactory()方法BeanFactoryPostProcessor;
  • 4、再来从容器中找到BeanFactoryPostProcessor组件,依次除法postProcessBeanFactory()方法。

ApplicationListener:监听容器中发布的事件。事件驱动模型的开发

 
  

ContextRefreshedEvent:容器刷新事件

ContextClosedEvent:容器死掉事件

步骤:

1、写一个事件监听器来监听某个事件(ApplicationEvent及其子类)

2、把监听器加入到容器中

3、只要容器中有相关事件的发布,我们就能监听到这个事件爱你:

 
  

4、发布一个事件:

 
  

1)、ContextRefreshedEvent事件;

  • 1、容器创建对象的时候会调用refresh方法
  • 2、finishRefresh()最后的刷新,调用了一个publicEvent(new ContextRefresh())方法
    • 【事件发布流程】
      • 1.获取到事件的多播器(派发器)getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
      • multicastEvent:事件派发。
      • 获取到所有的ApplicationListener
        • for (ApplicationListener<?> listener : getApplicationListeners(event, type))
        • 如果有Executor可以支持使用Executor进行异步派发。
        • 否则同步的方式直接执行listener方法。拿到listener回掉onApplicationEvent方法;
  • 3、容器关闭也会添加一个容器关闭事件。

【事件多播器】(事件派发器)

1、容器创建对象。refresh();

2、initApplicationEventMulticaster();ApplicationEventMulticaster;

  • 先去容器中找有没有id="applicatinEventMulticaster"的组件
  • 如果没有程序就用自己新建的simpleapplictionEventMulticaster,并加入到容器中,我们就可以在其他组件派发事件的时候自动注入applicationEventMulticaster

【容器中有哪些监听器】

1)、容器创建对象:refresh();

  1. .registerListeners();

    从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中:

    string[] listenerBeanNlmes = getBeanNamesForType(ApplicationListener.class,true, false)

    //将listener注册到ApplicationEventMulticaster中

    getApplicationEventMulticaster( ) . addApplicationListenerBean(listenerBeanName);

注解开发
 
  

使用@EventListener来进行注解开发

原理:

 
  
SmartInitializingSingleton
  • 1.ioc容器创建对象并refresh()
  • 2.finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;
    • 先创建所有的单实例bean;getBean();
    • 获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的
      • 如果是就调用afterSingletonsInstantiated()

3.Sping容器创建过程

Spring容器的创建和刷新refrsh()[创建刷新]

1、prepareRefresh();预处理工作

  • 1、initPropertySources()初始化一些属性设置。留给子类来做事情的。子类自定义个性化的属性设置方法
  • 2、getEnvironment().validateRequiredProperties();进行属性校验,校验属性和发等等
  • 3、earlyApplicationEvents = new LinkedHashSet<>(); 保存容器中的一些早期的事件

2、obtainFreshBeanFactory();获取beanfactory;

  • 1、refreshBeanFactory()刷新工厂
    • 创建了一个this.beanFactory = new DefaultListableBeanFactory();
    • 设置id
  • 2、getBeanFactory()返回了工厂;
  • 3、将beanfactory返回DefaultListableBeanFactory

3、prepareBeanFactory(beanFactory):BeanFactory的预准备工作(BeanFactory进行一些设置)

  • 1、设置Beanfactory的类加载器、支持表达式解析器。
  • 2、添加部分BeanPostProcessor[ApplicaitonContextAwareProcessor]
  • 3、配置忽略的自动装配的接口EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware
  • 4、registerResolvableDependency注册可以解析的自动装配。我们能直接在任何组建中自动装配的部分
  • 5、beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));添加许多的后置处理器
  • 6、添加编译时的Aspect支持;
  • 7、非beanFactory中注册一些能用的组件
    • environment[ConfigurableEnvironment]
    • systemProperties

4、postProcessBeanFactory(beanFactory);BeanFactory准备工作

 
  

=BeanFactory以及预准备工作===========

5、invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessors

  • BeanFactoryPostProcessors:BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的
  • 两个接口:BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor
    • 执行BeanFactoryPostProcessor方法
      • 1、获取所有的BeanDefinitionRegistryPostProcessor;
      • 2、看优先级排序PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor/postProcessor.postProcessBeanDefinitionRegistry(registry)
      • 3、在执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
        • postProcessor.postProcessBeanDefinitionRegistry(registry)
      • 4、最后执行没有实现任何优先级或者是顺序接口的
        • BeanDefinitionRegistryPostProcessors;postProcessor.postProcessBeanDefinitionRegistry(registry)
      • 再执行BeanFactoryPostProcessor方法
      • 1、获取所有的BeanFactoryPostProcessor
      • 之后方法大致和上面相同

6、registerBeanPostProcessors(beanFactory);执行BeanPostProcessors,Bean的后置处理器【拦截bean创建过程】

不同类型的BeanPostProcessor:在Bean创建前后的执行时机是不一样的

BeanPostProcessor:

DestructionAwareBeanPostProcessor:

InstantiationAwareBeanPostProcessor:

SmartInstantiationAwareBeanPostProcessor:

MergedBeanDefinitionPostProcessor:【internalPostProcessors】

  • 1、String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);获取所有的beanPostProcessor;后置处理器都默认可以有优先级
  • 2、先注册PriorityOrered优先级接口的BeanPostProcessor
    • 把每一个BeanPostProcessor添加到BeanFactory中
  • 3、再来注册Ordered接口的
  • 4、最后注册的没有实现任何优先级接口的
  • 5、最终注册MergedBeanDefinitionPostProcessor
  • 6、注册一个ApplicationListenerDatector:来在Bean创建完成后检查是否ApplicationListener,如果是
    • applicationcontext.addApplicationListener((ApplicationListener<?>) bean);

7、initMessageSource();初始化MessageSource组件(做国际化功能消息绑定。消息解析)

  • 1、获取BeanFactory
  • 2、容器中是否为id为messagesource组件,没有就整一个默认的messagesource
    • 如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource:
      • MessageSource:取出估计花配置文件中的某个key的值。
  • 3、把创建好的MessageSource注册在容器中,以后获取国际化标准配置文件的值得时候,可以自动驻入MessageSource;
    • beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,this.messageSource);
    • MessageSource.getMessage(String code,Object[] args,String defaultMessage,Local…)

8、initApplicationEventMulticaster();初始化事件派发器

  • 1、获取BeanFactory
  • 2、从BeanFactory中获取ApplicationEventMulticaster的
  • 3、没有配置就自动创建SimpleApplicationEventMulticaster
  • 4、将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接注入

9、onRefresh();初始化剩下的bean,留给子类的

  • 1、子类重写这个方法。在容器刷新的时候自定义做其他的事情。

10、registerListeners();

  • 1、从容器中拿到所有的ApplicationListener组件
  • 2、将每个监听器添加到事件派发器中
    • getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  • 3、派发之前步骤产生的事件。

11、finishBeanFactoryInitialization(beanFactory);初始化所有单实例的bean

  • 1、beanFactory.preInstantiateSingletons();初始化所有单实例的bean
    • 1、获取容器中的所有bean,依次进行初始化和创建对象。
    • 2、获取bean定义信息RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    • 3、如果!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()
      • 判断是否是isFactoryBean(beanName);是否实现了FactoryBean
      • 如果不是工厂getBean(beanName);
        • 1、getBean(beanName);ioc.getBean()
        • 2、doGetBean(name,null,null,false)
        • 3、先获取缓存中保存的单实例bean.如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
          • 从private final Map<String,object> singleton0bjects
        • 4、缓存中获取不到,开始Bean的创建流程
        • 5、标记当前bean已经创建
        • 6、获取当前Bean依赖的其他bean
        • 7、启动单实例bean的创建流程
          • 1、createBean(beanName,mbd,args);
          • 2、Object bean = resolveBeforeInstantiatino(beanName,mbdToUse);让beanpost提前拦截返回代理对象;
            • InstantiationAwareBeanPostProcessor:提前执行;
            • 先触发:postProcessBeforeInstantiation()
            • 如果有返回值:触发postProcessAfterInitialization
          • 3、如果前面的InstantiationAwareBeanPostProcessor没有返回代理对象
          • 4、doCreateBean()创建一个bean实例
            • 1、创建bean实例CreateBeanInstance
              • 解析bean类型。利用工厂方法,或者对象构造器,创建出bean实例。
            • 2、applyMergedBeanDefinitionPostProcessors(mbd, beanType,beanName);
              • 调用MergedBeanDefinitionPostProcessor bdp.postProcessMergedBeanDefinition(mbd, beanType,beanName) ;
            • 3、【Bean属性赋值populateBean(beanName,mbd, instancewrapper);
              • 1、赋值之前判断到InstantiationAwareBeanPostProcessor后置处理器;执行postProcessAfterInstantiation方法
              • 2、拿到InstantiationAwareBeanPostProcessor后置处理器
                • postProcessPropertyProcessor
              • 赋值之前:==========
              • 3、applyPropertyvalues( beanName,mbd,bw, pvs) ;应用bean属性的值。
            • 4、【bean】初始化initializeBean( beanName, exposedobject, mbd);
              • 1、invokeAwareMethods(beanName, bean);执行Aware接口的方法
                • BeanNameAwareBeanclaswareBeanFactorvAwarer
              • 2、【执行】applyBeanPostProcessorsBeforeInitialization
                • BeanPostProcessor.postProcessBeforeInitialization
              • 3、执行初始化方法invokeInitMethods(beanName,wrappedBean,mbd);
                • 1、是否是InitializingBean接口的实现;
                • 2、是否自定义初始化方法;
              • 4、【执行后置处理器初始化之后】applyBeanPostProcessorsAfterInitialization
                • BeanPostProcessor.postProcessAfterInitialization()
              • 5、注册Bean的销毁方法;
            • 5、将创建的Bean添加到缓存中singletonObjects;
              • ioc容器就是这些Map;很多的Map里面保存了单实例Bean,环境信息。。。。
    • 所有Bean都利用getBean创建完成以后;
      • 检查所有的Bean是否是SmartInitializingSingleton接口的,如果是,就执行afterSingletonsInstant
  • 12、finishRefresh()完成初始化创建工作。IOC容器创建完成
      1. 、initLifecycleProcessor();初始化和生命周期有关的后置处理器;LifecycleProcessor
        写一个LifecycleProcessor的实现类,可以在BeanFactory
        void onRefresh();
        void onclose();


    • 2)、getLifecycleProcessor( ).onRefreshO;
      • 拿到前面定义的生命周期处理器(BeanFactory)﹔回调
      1. . publishEvent(new ContextRefreshedEvent(this));发布
    • 4)、veBeansview.registerApplicationcontext(this);

总结

1、spring容器在启动的时候会保存所有注册进来的Bean定义信息

 
  

2、Spring容器在合适的时机创建这些bean

 
  

3、后置处理器:

 
  

4、事件驱动模型:

 
  

在这里插入图片描述

  1. 用户发送请求至前端控制器。
  2. 前端控制器收到请求调用处理器映射器。
  3. 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器,一并返回给前端控制器。
  4. 前端控制器调用处理器适配器,处理器适配器经过适配调用具体的处理器(controller,也叫后端控制器)。
  5. controller 执行完成返回 ModelAndView。
  6. 处理器适配器将 controller 执行结果 ModelAndView 返回给 前端控制器。
  7. 前端控制器将 ModelAndView 传给 视图解析器。
  8. 视图解析器解析后返回 VIew。
  9. 前端控制器根据 View 进行渲染视图(将模型数据填充至页面)。
  10. 前端控制器响应给用户。

● 原理:利用预编译的机制将sql语句的主干和参数分别传输给数据库。
● JDBC中使用PreparedStatement可以防止sql注入。
● mybatis中提供了两种方式:#{} 和 ${}、
● #{}: 在预处理时,会把参数部分作为一个占位符 ? 代替。能有效解决sql注入问题。
● ${}: 表示拼接字符串,并将接受的内容不加修饰符拼接到sql中,将会引起sql注入问题。



到此这篇java spring菜鸟教程(java spring 教程)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 字符串转interger(字符串转integer类型Java)2025-06-02 10:00:10
  • java自学app(Java自学视频)2025-06-02 10:00:10
  • java课程网课(java好的网课)2025-06-02 10:00:10
  • java内存模型jmm(Java内存模型怎么理解)2025-06-02 10:00:10
  • java课程设计网站(java程序设计精品课程网站)2025-06-02 10:00:10
  • Java字符串转数组(java字符串转数组注解)2025-06-02 10:00:10
  • java课程视频(java课程视频资源)2025-06-02 10:00:10
  • tcp工具类java(tcp java)2025-06-02 10:00:10
  • java爬虫教学(java爬虫入门)2025-06-02 10:00:10
  • java面试知识点(java面试必背)2025-06-02 10:00:10
  • 全屏图片