Spring基础笔记 (一)

简介: Spring基础笔记 (一)

Spring带给了我们什么?#


假如我们是第一次学习Spirng,我们大可不必关心spring带给我了我们什么便利,因为spring大概是web阶段筑基需要学习的第一个主流框架,初学难免会遇见各种各样的错误,所以尽管放心大胆的去学习如何使用就行了.先会用,其它的不用多想

过几天,用着熟悉了如何使用,再考虑spring究竟带给了我们什么便利也不迟, 那么,spring究竟带给了我们什么便利呢?


  • IOC(Inverse of Control),把对象的创建权反转给Spring容器,实现了解耦


我们使用Spring提供给我们的注解,把bean注册进IOC容器,进而把bean之间的依赖关系全部交给Spring管理,现在想想这绝对是一件超级赞的事情,可能原来的我会想,我自己可以new对象,干嘛非让Spring插一脚,是,假如我的项目就是个小demo全文一共三对象,完全顾的上来,那么spring对我来说就是累赘,但是!慢慢的接触的工程大了就会发现,离开了Spring,自己去管理那些对象之间的依赖会累死人的,而且SpringIOC的诞生也应正了bean的管理,完全不需要我们关系,我们关心的就是,我们如何向Spring索取依赖的Bean就行了,所以说Spring真的是web爱好者的小春天.


  • AOP(Aspect Oriented Programming),spring的aop


面向切面编程,aop说白了就是代码复用,把大量的重复代码从我们的业务逻辑中抽取出去,等程序运行的时候再动态的植入抽取出去的代码,这是件要多优雅就多优雅的事情!


应用:

  • 日志记录
  • 权限校验
  • 效率检查
  • 事务管理
  • 声明式事务


后端天天和数据库打交道,事务安全这样的不可能遇不见,我们这一代学习的人还真的是幸运,因为spring提供的声明式事务,我们不用再去苦苦的去写编程式事务,而且,现在spring4全面支持注解开发,我们甚至连配置文件都不用写,加一个注解就引入了spring的事务模块,激动不?


  • 方便集成其他开源框架


spring最擅长的事情就是整合这使它的生态变的超级庞大


例外给大家推荐一篇很棒的博客,里面详细图文论述了,spring究竟带给了我们什么?

spring实现解耦论述


注解版Spring-IOC怎么玩?#


组件注册#

只使用IOC,导入Spring-Context就可以


<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.7.RELEASE</version>
</dependency>


这个过程,我们要注意IOC以下几点


  • 组件注册的过程中有哪些过滤规则?
  • 如何控制组件的作用域(单例多例)?
  • 六种注册组件的方式?


组件注册及其过滤规则我串联在下面相邻的两部分里,这里先提一下Spring提供的所有过滤规则类型


在spring启动,开始扫描包,注册组件时,如果我们想按照我们的需求往IOC里面添加组件,就需要指定过滤规则,下面这五种类型的过滤规则,都源于我们在主配置类(相当于配置文件)上添加的@ComponentScan()包扫描注解


  • 按照注解过滤ANNOTATION


@ComponentScan(// 这个注解替换了原来配置文件中的包扫描
    value="com.changwu.tryspring",
    useDefaultFilters=false,
    includeFilters = {
      @Filter(type = FilterType.ANNOTATION, classes = Service.class)}
      )


  • 按照给定的类型过滤


@Configuration
@ComponentScan(// 这个注解替换了原来配置文件中的包扫描
        value="com.changwu.tryspring",
        useDefaultFilters=false,
        includeFilters = {
         //只要是给定的类型的类,就可以加载进IOC,包括它的子类
          @Filter(type = FilterType.ASSIGNABLE_TYPE,classes = BookDao.class)
        }
        )


  • 按照切面 (ASPECTJ) 基本不用
  • 按照正则 REGEX
  • 自定义规则 CUSTOM


@Configuration
@ComponentScan(// 这个注解替换了原来配置文件中的包扫描
    value="com.changwu.tryspring",
    useDefaultFilters=false,
    includeFilters = {
           // 只要是给定的类型的类,就可以加载进IOC,包括它的子类
            @Filter(type = FilterType.CUSTOM,classes = MyTypeFilter.class)
    }
)


注解版本中,配置类替换了原来的配置文件#


@Configuration 注解标记本类为配置类


那么我不加@Configuration注解,这个类就不能成为配置类吗? 里面通过@Bean注解就添加不进bean来了? 不是的, @Configuration标记会被Spring使用Cglib技术拦截下来,换言之我们得到的bean,不再是我们自己new 的那种小白bean,而是被代理过的Bean

那么什么才是百分百的配置类呢? 配置类是我们调用如下代码所需要的那个类


AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(配置类.class);


如下代码! 原来的包扫描被@ComponentScan 取代!!! 里面可以配置多个信息

  • 基础包信息value="com.XXX"
  • 排除被哪个注解标记的类excludeFilters = @Filter(type... classes...)
  • 只要被哪个注解标记的类,(配置文件版本的分两步!第一步禁用掉默认的过滤器),注解版同样分两步useDefaultFilters=false, includeFilters = @Filter(classes= Service.class)


excludeFilters 把bean排除出IOC容器!!! 一般都是按照注解, 后面是 !!注解!!的Class数组,

另外,过滤器Filter的过滤类型,默认为按照注解过滤!!!


还可以在配置类中往IOC容器中组成对象!!!@Bean,用的时候 @Autowired


默认情况下,无论获取多少次,都是单实例的!!!


/**
 * 配置类,等同于原来的配置文件
 *
 * @Author: Changwu
 * @Date: 2019/3/31 16:57
 */
@Configuration
@ComponentScan(// 这个注解替换了原来配置文件中的包扫描
        value="com.changwu.tryspring",
         excludeFilters = @Filter( type =FilterType.ANNOTATION, classes = Repository.class)
        )
// excludeFilters 把bean排除出IOC容器!!!  一般都是按照注解, 后面是  !!注解!!的Class数组,
public class MainConfig {
    /**
     * 给容器注册bean
     * 类型: 为返回值的类型
     * id 默认使用方法名
     * @return
     */
    @Bean(value = "stu")  // value可以自定义名字
    public Student getStu(){
        return  new Student("张三",23);
    }
}


此外在java8中,有如下代码,@ComponentSacn的倒数第二个注解是@Repeatble 意味着我们可以在主配置类上写多个@ComponentScan


*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {...}


自定义TypeFilter的过滤规则#


自定义注解,要求实现FilterType接口,实现他的match(),该方法里面的两个参数都是接口类型的,我们可以从它里面取出关于IOC所扫描到的所有类的源信息,满足我们的预期,返回true,表示允许注册进IOC


public class MyTypeFilter implements TypeFilter {
/**
 *
 * @param metadataReader  // 获取到当前的正在扫描的类的信息
 * @param metadataReaderFactory  // 可以获取到,其他任何类的信息
 * @return
 * @throws IOException
 */
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();//获取当前类的注解信息
    ClassMetadata classMetadata = metadataReader.getClassMetadata();// 获取当前正在扫描类的 类信息, 比如实现了什么接口,有什么方法
    Resource resource = metadataReader.getResource();// 获取类的资源信息, 比如在那个盘,路径
    String className = classMetadata.getClassName();
    System.out.println("---->"+className);
    // 自定义,如果有@Repository注解,注入进去
    Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();
    for (String annotationType : annotationTypes) {
        System.out.println("++++++"+annotationType);
    }
    if (annotationMetadata.hasAnnotation("org.springframework.stereotype.Service")){
        return true;
    }
 /*   if (className.contains("er")){
    return true;
}*/
    return false;
}
}


@Scope, 设置组件的作用域#


容器中的对象默认都是单实例的!!!,我们使用@Scope 注解改变这种状态


/*
    String SCOPE_SINGLETON = "singleton";  单例
    String SCOPE_PROTOTYPE = "prototype";  多例
   */
    @Scope(scopeName = "prototype")
    @Bean(value = "stu2")
    public Student getStu2(){
        return new Student("李四",24);
    }
}


观察在单实例和多实例情况下,bean创建的时机


  • 默认在单实例的情况下,ioc容器创建完,直接加载bean


但是以后每次获取都会都是从IOC容器中获取

懒加载@Lazy! 针对单实例Bean,我们知道,容器启动的时候,就会创建一个唯一的bean,我们使用懒加载可以做到,在第一次使用的时候加载bean


  • 多实例情况下,只有在获取类时,IOC容器才会创建bean,!!!


以后每次获取Bean,ioc容器都会调用那个方法去new Bean


六种给容器注册组件的方法#

着重看一种,按照条件注册bean @Conditional springboot底层大量的使用!!!#


它的实现方式和自定义过滤条件相似

@Conditional : 按照条件注册bean


// 既可以标在类上,也可以标在方法上
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {
  /**
   * 所有的条件,都必须是注册过的!!!.
   */
  Class<? extends Condition>[] value();
}


解释一下怎么用:

  • 它是个接口,需要的属性名为 value, 值是Class数组 ,可以进一步看到它的泛型是Condition接口 我们自己实现接口,重写里面的方法match(),根据方法提供的参数可以获取到我们想要的任何信息,返回true表示满足条件,注册bean,否则不注册


其他注册组件的方法


  • 方式1: 包扫描+注解 (@Cotroller @Service @Repository等等注解的类可以被IOC扫描到,添加进容器)


这种方法有局限性!!!, 只能是我们自己写的类, id为首字母小写的类名


  • 方式2: 在配置类内部 使用: @Bean注解,


更多的使用它注册第三方bean


  • 方式3: 在配置类头上使用  @Import(XXX.class,YYY.class)


解放了第二种通过@Bean还的自己new的缺陷!!! 组册进IOC中的组件的默认id,是组件的全类名


  • 方式4: @Import({Color.class, MyImportSelector.class})


实现ImportSelector接口: 返回需要导入的组件的全类名数组,完成批量导入


  • 方式5: 手动注册@Import({Color.class,MyImportSelector.class, MyImportBeanDefinitionRegisrar.class})


实现ImportBeanDefinitionRegistrar接口: 它里面的registerBeanDefinitions()方法的第二个参数就是BeanDefinitionRegistry, 所有bean注册进IOC容器都经由他完成,因此我们可以手动注册bean, 还可以通过第一个参数获取当前标注@Import注解的类的全部注解信息,加上第二个参数可以获取当前IOC容器的全部信息,动态判断是否要注入类到IOC

同时,第五种在SpringBoot中得到了大量的使用,实现SpringBoot的自动配置


  • 方式6 : 使用Spring提供的FactoryBean (工厂bean)


  1. 自己实现FactoryBean接口,重写三个方法
  2. @Bean,把自己实现的工厂bean添加到IOC
  3. 测试自己实现的BeanFactory的类型,是我们指定的泛型的类型的!!!
  4. 想获取到工厂的话, 需要添加前缀&


AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig02.class);
Object getFB1 = applicationContext.getBean("&getFB");
Object getFB2 = applicationContext.getBean("getFB");



相关文章
|
1月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
26 1
|
1月前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
53 0
|
2月前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
【Java笔记+踩坑】Spring Data JPA
|
2月前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
5月前
|
NoSQL 前端开发 Java
技术笔记:springboot分布式锁组件spring
技术笔记:springboot分布式锁组件spring
55 1
|
5月前
|
Java Linux 程序员
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
|
5月前
|
XML Java 数据安全/隐私保护
技术笔记:Spring中的通知(Advice)和顾问(Advisor)
技术笔记:Spring中的通知(Advice)和顾问(Advisor)
73 0
|
6月前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
113 2
|
6月前
|
缓存 监控 Java
【Spring系列笔记】AOP
面向切面编程就是面向特定方法编程。通过将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来,提供一种更好的代码模块化和可维护性。 横切关注点指的是在应用程序中横跨多个模块或层的功能,例如日志记录、事务管理、安全性、缓存、异常处理等。
96 0
|
6月前
|
存储 缓存 Java
【Spring系列笔记】依赖注入,循环依赖以及三级缓存
依赖注入: 是指通过外部配置,将依赖关系注入到对象中。依赖注入有四种主要方式:构造器注入、setter方法注入、接口注入以及注解注入。其中注解注入在开发中最为常见,因为其使用便捷以及可维护性强;构造器注入为官方推荐,可注入不可变对象以及解决循环依赖问题。本文基于依赖注入方式引出循环依赖以及三层缓存的底层原理,以及代码的实现方式。
100 0
下一篇
无影云桌面