spring简介

spring是一种开源轻量级框架,是为了解决企业应用程序复杂性而创建的

spring是企业应用开发的“一站式”框架,致力于为javaEE应用的各层(表现层、业务层、持久层)开发提供解决方案,而不仅仅是某一层的解决方案

spring并不会代替原有的那些框架,而是以高度的开放性,与已存在的框架进行整合

通过spring技术,不需要重复制造轮子,在已有较好解决方案的技术领域绝不重复实现。例如,对象持久化和OR映射,spring只对现有的JDBC、Hibernate等技术提供支持,使之更加便于使用,不需要做重复的实现


spring组成结构

spring core:spring核心,是框架最基础的部分,提供spring IOC和依赖注入的功能

spring context:spring上下文容器,是对BeanFactory功能增强的一个子接口

spring web:spring的web模块,提供了对web应用开发的支持

spring mvc:针对web应用mvc思想的实现

spring orm:支持对流行ORM框架的整合,mybatis、hibernate

spring dao:提供对JDBC的抽象,简化JDBC编码

spring aop:面向切面编程,提供了与AOP联盟兼容的编程实现


spring常用组件

@Configuration

在类上使用,指定该类为配置类,相当于配置文件

@Bean

在方法上使用,向容器注册一个bean,返回值是bean的类型,bean的id默认是方法名,可以设置bean的id @Bean(name)

/**
* 配置类,相当于配置文件的作用
* @author qf
* @create 2019-05-20 9:55
*/
@Configuration
public class MainConfig {
/**
* 向容器注册一个bean,返回类型为bean的类型
* 默认方法名是bean的id名,可以通过配置@Bean(yoursName)设置id
* @return
*/
@Bean("wxf")
public Person person(){
return new Person("wxf",19);
}
}

AnnotationConfigApplicationContext

根据注解配置类获取spring的IOC容器

@Test
public void testConfig(){
/**
* 注解配置来获取spring IOC容器
*/
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = (Person) context.getBean("wxf");
System.out.println(person);
}

@ComponentScan

设置扫描规则,指定要扫描的包,扫描带有@Controller、@Service、@Repository以及@Component注解的类

value:指定要扫描的包

excludeFilters:Filters[],指定扫描的时候按照什么规则排除哪些组件  

includeFilters:Filters[],指定扫描时按照什么规则只包含哪些组件

  扫描规则

    FilterType.ANNOTATION:按照注解

    FilterType.ASSIGNABLE_TYPE:按照给定的类型;比如按BookService类型

    FilterType.ASPECTJ:使用ASPECTJ表达式

    FilterType.REGEX:使用正则指定

    FilterType.CUSTOM:使用自定义规则,自已写类,实现TypeFilter接口

  classes:

    Controller.class:表示扫描的是使用了@Controller注解的类

    Service.class、Repository.class、Component.class

useDefaultFilters:默认true,扫描所有组件;false:使用自定义扫描范围  

@Configuration
@ComponentScan(value = "com.enjoy.study.cap2",excludeFilters={
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class})
},useDefaultFilters = false)

public class MainConfig {
@Bean()
public Person person(){
return new Person("wxf",19);
}
}

案例:测试自定义规则使用

1. 自定义过滤规则类

public class MyTypeFilter implements TypeFilter {
/**
*
* @param metadataReader:读取到的当前正在扫描的类的信息
* @param metadataReaderFactory:可以获取其它任何类的信息的工厂
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类的注解信息
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类路径)
Resource resource = metadataReader.getResource();
//获取当前类的类名
String className = classMetadata.getClassName(); if(className != null && className.contains("Dao")){
return true;
}
return false;
}
}

2. 在配置类中使用

com.enjoy.study.cap2包下

  

@Configuration
@ComponentScan(value = "com.enjoy.study.cap2",includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)

public class MainConfig {
@Bean()
public Person person(){
return new Person("wxf",19);
}
}

3. 测试方法,打印spring的IOC容器中的所有对象

@Test
public void testConfig2(){
/**
* 注解配置来获取spring IOC容器
*/
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
//获取类名
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}

4. 打印结果

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
userDao
person

@Scope

spring中默认的bean是单例的,@Scope(value)可以设置bean实例的不同创建方式

singleton:默认方式,单实例,IOC容器启动时调用方法创建对象并放入IOC容器中,以后每次获取的就是从容器中拿到的同一个实例对象

prototype:多实例,IOC容器启动时并不会调用方法创建对象,以后每次获取时都调用方法创建一个对象

request:主要针对web应用,一个请求创建一个对象

session:主要针对web应用,一次session会话创建一个对象

@Configuration
public class MainConfig { @Bean
@Scope(value = "prototype")
public Person person(){
return new Person();
}
} @Test
public void getBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(com.enjoy.study.cap3.MainConfig.class);
Object person1 = context.getBean("person");
Object person2 = context.getBean("person");
System.out.println(person1 == person2);
}

没使用@Scope注解之前返回true,因为默认使用singleton模式;添加@Scope("prototype")后返回false

@Lazy

懒加载

默认情况下,启动容器是创建对象;配置懒加载后,启动容器时不创建对象,在第一次使用bean时创建对象

@Configuration
public class MainConfig { @Bean
@Lazy
public Person person(){
System.out.println("IOC容器创建对象");
return new Person("qf",21);
}
} public class LazyTest {
/**
* 测试IOC容器创建bean实例对象的时机
*/
@Test
public void lazyT(){
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("IOC容器启动完成"); context.getBean("person");
}
}
/* 注释@Lazy */
IOC容器创建对象
IOC容器启动完成 /* 不注释@Lazy */
IOC容器启动完成
IOC容器创建对象

使用懒加载时,第一次context.getBean时才会创建实例对象


@Conditional

条件注册bean

IOC容器注册bean时,使用@Conditional(MyCondition.class),使得满足自定义条件类MyCondition的bean才会被注册到IOC容器中

MyCondition类必须实现Condition接口,实现其中的match方法

测试案例:根据不同操作系统,Windows系统时wxf注入IOC,linux系统下qf注入IOC容器

条件类

public class MyWinCondition implements Condition {
/**
*
* @param conditionContext :判断条件能使用的上下文
* @param annotatedTypeMetadata :注释信息
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取IOC容器使用的BeanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry(); //获取当前环境的操作系统名
String osName = environment.getProperty("os.name");
if(osName != null && osName.contains("Windows")){
return true;
}
return false;
}
}

public class MyLinuxCondition implements Condition {
    /**
*
* @param conditionContext :判断条件能使用的上下文
* @param annotatedTypeMetadata :注释信息
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取当前环境的操作系统名
String osName = environment.getProperty("os.name");
if(osName != null && osName.contains("Linux")){
return true;
}
return false;
}
}

配置类

@Configuration
public class Cap5MainConfig { @Bean("person")
public Person person(){
System.out.println("person 被注册到IOC容器");
return new Person();
} @Conditional(MyWinCondition.class)
@Bean("wxf")
public Person wxf(){
System.out.println("wxf 被注册到IOC容器");
return new Person();
} @Conditional(MyLinuxCondition.class)
@Bean("qf")
public Person qf(){
System.out.println("qf 被注册到IOC容器");
return new Person();
} }

测试类

public class Cap5Test {

    @Test
public void testGetBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(Cap5MainConfig.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}

打印结果

person 被注册到IOC容器
wxf 被注册到IOC容器
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
cap5MainConfig
person
wxf

当前系统是Windows,所以qf没被注册到IOC容器中


@Import

注册bean

在类上使用的注解

使用:

  1. @Import({Person.class})或者@Import({Person.class,User.class}):容器中会自动注册这个bean,id是这个bean的全路径名
  2. @Import+ImportSelector接口:ImportSelector接口返回需要导入的组件的全类名数组
  3. @Import+ImportBeanDefinitionRegistrar接口:自定义注册bean到容器中

测试

测试类

public class Cap6Test {
@Test
public void importTest(){
ApplicationContext context = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println("name = " + name);
}
}
  1. @Import({Person.class})或者@Import({Person.class,User.class})

    配置类
    @Configuration
    @Import({User.class})
    public class Cap6MainConfig { }

    结果
    name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    name = org.springframework.context.annotation.internalRequiredAnnotationProcessor
    name = org.springframework.context.annotation.internalCommonAnnotationProcessor
    name = org.springframework.context.event.internalEventListenerProcessor
    name = org.springframework.context.event.internalEventListenerFactory
    name = cap6MainConfig
    name = com.enjoy.study.cap6.pojo.User
  2. @Import+ImportSelector接口
    配置类
    @Configuration
    @Import({User.class, MyImportSelector.class})
    public class Cap6MainConfig { }

    自定义导入选择器
    /**
    * 自定义逻辑返回要导入容器的组件
    * @author qf
    * @create 2019-05-21 13:57
    */
    public class MyImportSelector implements ImportSelector {
    /**
    *
    * @param annotationMetadata 当前标注@Import注解的类的所有注解信息,不仅仅能获取到@Import注解,可以获取该类的所有注解
    * @return
    */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    /**
    * 注意:不要返回null,返回null,会报空指针
    */
    return new String[]{"com.enjoy.study.cap6.pojo.Student","com.enjoy.study.cap6.pojo.Teacher"};
    }
    }

    结果
    name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    name = org.springframework.context.annotation.internalRequiredAnnotationProcessor
    name = org.springframework.context.annotation.internalCommonAnnotationProcessor
    name = org.springframework.context.event.internalEventListenerProcessor
    name = org.springframework.context.event.internalEventListenerFactory
    name = cap6MainConfig
    name = com.enjoy.study.cap6.pojo.User
    name = com.enjoy.study.cap6.pojo.Student
    name = com.enjoy.study.cap6.pojo.Teacher 
  3. @Import+ImportBeanDefinitionRegistrar接口
    /**
    * 自定义bean注册类
    * @author qf
    * @create 2019-05-21 14:09
    */
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
    *
    * @param annotationMetadata:当前类的注解信息
    * @param beanDefinitionRegistry:BeanDefinition注册类,把所有需要添加到容器的bean,
    * 调用BeanDefinitionRegistry的registerBeanDefinitions方法自定义手工注册进来
    */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    //容器中是否存在Student
    boolean definitionStu = beanDefinitionRegistry.containsBeanDefinition("com.enjoy.study.cap6.pojo.Student");
    //容器中是否存在Teacher
    boolean definitionTea = beanDefinitionRegistry.containsBeanDefinition("com.enjoy.study.cap6.pojo.Teacher"); //如果容器中存在Student和Teacher
    if(definitionStu && definitionTea){
    RootBeanDefinition beanDefinition = new RootBeanDefinition(User.class);
    /**
    * 第一个参数:自定义bean的名,不一定是全路径
    * 第二个参数:beanDefinition,bean的定义信息(类型,作用域等)
    */
    beanDefinitionRegistry.registerBeanDefinition("user",beanDefinition);
    }
    }
    }

    配置类
    @Configuration
    @Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
    public class Cap6MainConfig { }

    结果
    name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    name = org.springframework.context.annotation.internalRequiredAnnotationProcessor
    name = org.springframework.context.annotation.internalCommonAnnotationProcessor
    name = org.springframework.context.event.internalEventListenerProcessor
    name = org.springframework.context.event.internalEventListenerFactory
    name = cap6MainConfig
    name = com.enjoy.study.cap6.pojo.Student
    name = com.enjoy.study.cap6.pojo.Teacher
    name = user  

FactoryBean

主要功能是将bean注册到容器中

public interface FactoryBean<T> {
T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton();
}
  • getObject():容器调用getObject方法返回对象,并将该对象放入容器中
  • getObjectType():返回对象类型
  • isSingleton():是否是单例进行控制

测试一

自定义FactoryBean
public class MyFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
} @Override
public Class<?> getObjectType() {
return User.class;
} @Override
public boolean isSingleton() {
return false;
}
}

配置类
@Configuration
public class Cap6MainConfig { @Bean
public MyFactoryBean user(){
return new MyFactoryBean();
}
}

结果
name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor
name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor
name = org.springframework.context.annotation.internalRequiredAnnotationProcessor
name = org.springframework.context.annotation.internalCommonAnnotationProcessor
name = org.springframework.context.event.internalEventListenerProcessor
name = org.springframework.context.event.internalEventListenerFactory
name = cap6MainConfig
name = user

测试二

@Test
public void factoryBean() throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
//获取自定义FactoryBean本身
Object bean = context.getBean("&user");
System.out.println(bean.getClass());
System.out.println("--------------");
//获取通过自定义FactoryBean注册到容器中的bean对象
bean = context.getBean("user");
System.out.println(bean.getClass());
}

结果
class com.enjoy.study.cap6.MyFactoryBean
--------------
class com.enjoy.study.cap6.pojo.User

spring中注册bean的方式总结:

  1. 包扫描(@ComponentScan)+组件标注注解(@Controller、@Service、@Repository、@Component)
  2. @Bean【导入第三方类或者包的组件,比如Person是第三方提供的类,使用@Bean注册到IOC容器】
  3. @Import【快速给容器导入一个组件】
  4. 实现FactoryBean接口

spring(一):spring的基础以及组件的更多相关文章

  1. 0047 Spring的AOP入门基础--切面组件--通知--切入点

    AOP的全称是Aspect Oriented Programming,面向切面编程. 切面是什么呢,就是一个Java类.之所以叫切面,就是说在调用其他一些类的方法的某个时候(之前,之后,抛异常等),调 ...

  2. Spring IOC基础回顾 — 组件扫描和装配

    目录 注解形式配置应用IOC 1. 组件自动扫描 2. 组件依赖:为bean添加注解,实现自动注入 3. Spring IOC应用小结 注解形式配置应用IOC 在类定义.方法定义.成员变量定义前使用, ...

  3. Spring笔记01(基础知识)

    1.基础知识 01.Spring:轻量级Java EE开源框架,它是由Rod Johnson为了解决企业应用程序开发的复杂性而创建. 02.目标:实现一个全方位的整合框架,实现“一站式”的企业应用开发 ...

  4. spring batch(一):基础部分

    spring batch(一):基础部分 博客分类: Spring java   spring batch 官网: http://www.springsource.org/spring-batch 下 ...

  5. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring目录结构和基础JAR包介绍

    可以通过网址 http://repo.spring.io/simple/libs-release-local/org/springframework/spring/ 下载名称为 springframe ...

  6. Spring 框架介绍 [Spring 优点][Spring 应用领域][体系结构][目录结构][基础 jar 包]

    您的"关注"和"点赞",是信任,是认可,是支持,是动力...... 如意见相佐,可留言. 本人必将竭尽全力试图做到准确和全面,终其一生进行修改补充更新. 目录 ...

  7. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

  8. Spring Boot 入门之基础篇(一)

    原文地址:Spring Boot 入门之基础篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是 ...

  9. Spring 注解原理(一)组件注册

    Spring 注解原理(一)组件注册 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 当我们需要使用 Spring 提供的 ...

随机推荐

  1. [NOI1999]生日蛋糕(搜索)

    [NOI1999]生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半 ...

  2. 前端面试题:不使用loop循环,创建一个长度为100的数组,并且每个元素的值等于它的下标,,怎么实现好?

    昨天,看这道题,脑子锈住了,就是没有思路,没看明白是什么意思?⊙﹏⊙|∣今天早上起床,想到需要思考一下这个问题. 当然,我没想明白为什么要这样做?(创建一个长度为100的数组,并且每个元素的值等于它的 ...

  3. Oracle分组函数之Grouping Sets

    功能介绍: 自定义分组的字段 创建表: 插入测试数据: Grouping Sets(null,t.classid,(t.classid,t.studentname)),类似于ROLLUP Select ...

  4. Linux内核设计与实现 总结笔记(第六章)内核数据结构

    内核数据结构 Linux内核实现了这些通用数据结构,而且提倡大家在开发时重用. 内核开发者应该尽可能地使用这些数据结构,而不要自作主张的山寨方法. 通用的数据结构有以下几种:链表.队列.映射和二叉树 ...

  5. 小陈现有2个任务A,B要完成,每个任务分别有若干步骤如下 一道网上没啥题解的难题(至少我是这么觉得的)

    小陈现有2个任务A,B要完成,每个任务分别有若干步骤如下:A=a1->a2->a3,B=b1->b2->b3->b4->b5.在任何时候,小陈只能专心做某个任务的一 ...

  6. Bing Advanced Search Tricks You Should Know

    Bing is one of the world's most popular search engines that has gained many fans with its ease of us ...

  7. Docker容器日常操作命令

    在Docker的运用中,从下载镜像,启动容器,在容器中输入命令来运行程序,这些命令都是手工一条条往里输入的,无法重复利用,而且效率很低.所以就需要一 种文件或脚本,我们把想执行的操作以命令的方式写入其 ...

  8. 将python文件打包成exe可执行文件

    操作系统:win8-64位 python版本:3.5 pyInstaller版本:3.2(下载地址:http://www.pyinstaller.org/) pywin32版本:pywin32-219 ...

  9. JS-计算身份证校验码(最后一位)

    在线预览 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  10. 简单了解winform

    WinForm是·Net开发平台中对Windows Form的一种称谓. Windows窗体可用于设计窗体和可视控件,以创建丰富的基于Windows的窗体应用程序.可以访问数据库中的数据,并在窗体上显 ...