spring注解驱动开发(一)

news/2024/7/8 2:55:37

1、需要导入的spring框架的依赖

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

2、@Configuration

设置类为配置类

3、AnnotationConfigApplicationContext

  • 通过配置类获取上下文环境applicationContext
  • 可以通过getBeanDefinitionNames()获得配置类中配置的各类Bean
  • 也可以使用getBeanNamesForType()通过类型来获得bean的name(id)
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String str : beanDefinitionNames) {
      System.out.println(str);
    }

4、@Bean

  • 注册一个javaBean
  • 默认用方法名作为Bean的id
  • 使用AnnotationConfigApplicationContext的实例 通过getBean来获得这个Bean
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
  @Bean
  public Person person(){
    return new Person("lisi",20);
  }
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    Person bean = applicationContext.getBean(Person.class);
    System.out.println(bean);

5、@ComponentScan

为配置类开启组件扫描

  • 放在配置类的上方,指定扫描的包路径如
@ComponentScan(value = "com.atguigu")
  • 还可以使用excludeFilter来设置类扫描规则如包含、排除,excludeFilter需要设置为一个数组
    排除
    包含使用excludeFilter,并为其设置一个过滤数组,来指定需要过滤掉那些组件
@Configuration
@ComponentScan(value = "com.atguigu",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
        classes ={Controller.class,Service.class} )
})
public class MainConfig {
  @Bean
  public Person person(){
    return new Person("lisi",20);
  }
}

包含
包含使用includeFilter,包含里面需要设置使用默认规则为false

@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
        classes ={Controller.class,Service.class} )},useDefaultFilters = false)
public class MainConfig {
  @Bean
  public Person person(){
    return new Person("lisi",20);
  }
}

还可以设置按给定类型过滤

@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,
                classes ={Controller.class,Service.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
                classes ={BookService.class})
},useDefaultFilters = false)
public class MainConfig {
  @Bean
  public Person person(){
    return new Person("lisi",20);
  }
}

其他可以设置的过滤方式还可以有:

  • 使用FilterType.ASPECTJ按照ASPECTJ表达式
  • 使用FilterType.REGEX按照REGEX正则表达式
  • 使用FilterType.CUSTOM按照自定义规则过滤(需要实现TypeFilter接口)

自定义过滤规则

public class MyTypeFilter implements TypeFilter {
  /*
  metadataReader:读取到的当前正在扫描的类的信息
  metadataReaderFactory:可以获取到其他任何类的信息
   */

  @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(resource);
    System.out.println(className);
     if(className.contains("er")){
      return true;
    }
    return false;
  }
}

设置自定义规则

@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,
                classes = {MyTypeFilter.class})
},useDefaultFilters = false)
public class MainConfig {
  @Bean
  public Person person(){
    return new Person("lisi",20);
  }
}

测试代码

@Test
  public void testbeans() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String str : beanDefinitionNames) {
      System.out.println(str);
    }
  }

测试结果

测试规则打印内容

file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/bean/Person.class]
com.atguigu.bean.Person
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/config/MyTypeFilter.class]
com.atguigu.config.MyTypeFilter
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/controller/BookController.class]
com.atguigu.controller.BookController
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/dao/BookDAO.class]
com.atguigu.dao.BookDAO
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/service/BookService.class]
com.atguigu.service.BookService
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/test/MainTest.class]
com.atguigu.test.MainTest

测试类打印过滤结果

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService

6、@Controller

将类配置为Controller类

7、@Service

将类配置为service类

8、@Repository

将类配置为dao操作的类

9、@Component

将类配置为通用类组件

10、@Scope

调整bean的作用域范围,默认单实例,可以修改为多实例
Bean是默认单实例的,通过指明prototype(多实例)和singleton(单实例)属性指明是否单实例

  • prototype:多实例
  • singleton:单实例
  • request:同一次请求创建一个实例
  • session:同一个session创建一个实例
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
  //Bean是默认单实例的,通过指明prototype(多实例)和singleton(单实例)属性指明是是否单实例
  //prototype:多实例
  //singleton:单实例
  //request:同一次请求创建一个实例
  //session:同一个session创建一个实例
  @Scope("prototype")
  @Bean("person")//指定bean的自定义id
  public Person person(){
    return new Person("张三",20);
  }
}

测试

  @Test
  public void testbeans() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
	Object bean1 = applicationContext.getBean("person");
	Object bean2 = applicationContext.getBean("person");
    System.out.println(bean1==bean2);
  }

测试结果为false

11、@Lazy懒加载

实例默认在容器创建时立即加载
使用@Lazy后,当需要创建实例时才被加载

  • 不使用懒加载
    实体类构造函数
  public Person(String name, Integer age) {
    System.out.println("给容器添加Person对象");

    this.name = name;
    this.age = age;
  }

测试代码

@Test
  public void testbeans() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器已创建完成");
    //没有获取类的代码,单实际上类的实例已经被加载进容器了
  }

测试结果

给容器添加Person对象
容器已创建完成
  • 使用懒加载
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }
}

测试代码

@Test
  public void testbeans() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器已创建完成");
    Object bean1 = applicationContext.getBean("person");//这一句出现后才加载Person类

  }

测试结果

给容器添加Person对象
容器已创建完成

12、@Conditional

  • 按一定条件注册bean,满足条件就给容器注册bean,否则不注入
  • 要作为自定义条件,需要创建自定义condition类,并要实现Condition接口,并实现match方法
  • conditional不仅可以标在方法上,还可以标记在类上
//判断是否是Linux系统的条件
//要作为自定义条件,要实现Condition接口,并实现match方法
//AnnotatedTypeMetadata:注释信息
public class LinuxCondition implements Condition {
  @Override
  public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
    //判断linux洗洗
    ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
    //获取类加载器
    ClassLoader classLoader = conditionContext.getClassLoader();
    //获得当前环境信息
    Environment environment = conditionContext.getEnvironment();
    //获取到bean定义的注册类
    BeanDefinitionRegistry registry = conditionContext.getRegistry();

    String OSproperty = environment.getProperty("os.name");
    if (OSproperty.contains("Mac OS X")){
      return true;
    }

    return false;
  }
}

另一个自定义条件

public class WindowsCondition implements Condition {
  @Override
  public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
    Environment environment = conditionContext.getEnvironment();
    //获取操作系统信息
    String OSproperty = environment.getProperty("os.name");
    if (OSproperty.contains("Window")){
      return true;
    }
    return false;
  }
}

配置类信息


@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }

  @Conditional({WindowsCondition.class})
  @Bean("male")
  public Person personMale(){
    return new Person("lisi",33);
  }

  @Conditional({LinuxCondition.class})
  @Bean("female")
  public Person personFemale(){
    return new Person("wanger",23);
  }
}

测试类信息

@Test
  public void testBeans() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

    //获取ioc容器的运行环境
    ConfigurableEnvironment environment=applicationContext.getEnvironment();
    //获取操作系统名称
    String property = environment.getProperty("os.name");
    System.out.println(property);

    String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
    for (String name:namesForType) {
      System.out.println(name);
    }

  }

测试结果

Mac OS X
person
female

13、给IOC容器中注册组件的5种方法

  1. 包扫描+组件类上标注注解:(@Controller,@Service,@Repository,@Component)
  2. @Bean:导入第三方包的组件
  3. @Import:快速给容器导入一个组件
    1)@Import(要导入到容器的组件),容器中就会自动注册这个逐渐,id默认是全类名
    2)ImportSelector:返回需要导入的组件的全类名数组

4.使用ImportBeanDefinitionRegistrar
5.使用Spring提供的FactoryBean(工厂bean)注册组件
1)默认获得的是工厂bean调用getObject创建的对象
2)要获取工厂bean本身,需要给id前面加一个&标识

14、@Import 快速导入一个类

使用@Import快速为配置类导入一个bean类
可以同时导入多个bean类
需要再配置类上方书写

  • 创建被导入的bean类
public class Color {
}
public class Red {
}
  • 给配置类导入该类
@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class})//在这里进行快速地导入,可以是数组形式
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }

  @Conditional({WindowsCondition.class})
  @Bean("male")
  public Person personMale(){
    return new Person("lisi",33);
  }

  @Conditional({LinuxCondition.class})
  @Bean("female")
  public Person personFemale(){
    return new Person("wanger",23);
  }
}

测试类代码

 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

  @Test
  public void testImport(){
    printBeans(applicationContext);
  }

  private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String name:beanDefinitionNames) {
      System.out.println(name);
    }
  }

测试结果

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
person
female

15、ImportSelector接口导入一个类

  • ImportSelector:返回需要导入的组件的全类名数组
  • 需要实现ImportSelector接口并改写selectImports方法

创建需要被导入的类

public class Blue {
}
public class Yellow {
}

创建自己的Import类

public class MyImportSelect implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
    //返回值是要导入到容器中的组件全类名
    //annotationMetadata:注解信息
    return new String[]{"com.atguigu.bean.Blue", "com.atguigu.bean.Yellow"};
  }
}

在配置类中设置@Import导入的自定义类选择器

注意:@Import({Color.class, Red.class,MyImportSelect.class})

@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class})
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }

  @Conditional({WindowsCondition.class})
  @Bean("male")
  public Person personMale(){
    return new Person("lisi",33);
  }

  @Conditional({LinuxCondition.class})
  @Bean("female")
  public Person personFemale(){
    return new Person("wanger",23);
  }
}

测试代码

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

  @Test
  public void testImport(){
    printBeans(applicationContext);
  }

  private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String name:beanDefinitionNames) {
      System.out.println(name);
    }
  }

测试结果
Color,Red,Blue,Yellow都有了

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female

16、使用ImportBeanDefinitionRegistrar接口导入类

自定义导入的类定义,需要实现ImportBeanDefinitionRegistrar接口,并重写 registerBeanDefinitions方法

创建一个需要被注入的类

public class RainBow {
}

创建自定义的注册类信息类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
  //annotationMetadata:当前类的注解信息
  //beanDefinitionRegistry:beanDefinition注册类
  //把所有需要添加到容器中的bean,调用beanDefinitionRegistry.registerBeanDefinition手动注册类
  @Override
  public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    boolean red = beanDefinitionRegistry.containsBeanDefinition("com.atguigu.bean.Red");//判断定义中是否有红色
    boolean blue = beanDefinitionRegistry.containsBeanDefinition("com.atguigu.bean.Blue");//判断定义中是否有蓝色
    if(red && blue){
      //指定bean名
      RootBeanDefinition rainbowDefinition = new RootBeanDefinition(RainBow.class);
      //注册了一个bean,并指定了一个类名(别名)
      beanDefinitionRegistry.registerBeanDefinition("rainbow", rainbowDefinition);
    }
  }
}

在配置类中进行配置
注意:@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})

@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }

  @Conditional({WindowsCondition.class})
  @Bean("male")
  public Person personMale(){
    return new Person("lisi",33);
  }

  @Conditional({LinuxCondition.class})
  @Bean("female")
  public Person personFemale(){
    return new Person("wanger",23);
  }
}

测试类

 @Test
  public void testImport(){
    printBeans(applicationContext);
  }

  private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String name:beanDefinitionNames) {
      System.out.println(name);
    }
  }

测试结果
显示了rainbow

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female
rainbow

17、使用FactoryBean接口导入类

创建自定义工厂类,实现FactoryBean接口,并改写一下方法
getObject() //返回工厂生产的类对象
getObjectType()//返回工厂生产的类类型
isSingleton() //返回单例

创建自定义工厂类
这里实现FactoryBean接口,实现三个方法,注意泛型中使用Color类


public class ColorFactory implements FactoryBean<Color> {
  //返回一个Color对象,这个对象会添加到容器中

  @Override
  public Color getObject() throws Exception {
    System.out.println("color factory generate a instance");
    return new Color();
  }

  @Override
  public Class<?> getObjectType() {
    return Color.class;
  }


  @Override
  public boolean isSingleton() {
    //true:返回单例,在容器中保存一份
    //false:返回多份类实例,每次获取工厂bean都会创建一个新的对象
    return false;
  }
}

在配置类中定义这个类组件
注意:
@Bean
public ColorFactory colorFactoryBean(){
return new ColorFactory();
}
}

@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
//  @Scope("prototype")
  @Lazy
  @Bean("person")//指定bean的自定义id
  public Person person(){

    return new Person("张三",20);
  }

  @Conditional({WindowsCondition.class})
  @Bean("male")
  public Person personMale(){
    return new Person("lisi",33);
  }

  @Conditional({LinuxCondition.class})
  @Bean("female")
  public Person personFemale(){
    return new Person("wanger",23);
  }

  @Bean
  public ColorFactory colorFactoryBean(){
    return new ColorFactory();
  }
}

测试类

public class MainTest {
  AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

  @Test
  public void testImport(){
    printBeans(applicationContext);

    //工厂bean获取的是调用的是getObject创建的对象(Color类)
    Object bean1 = applicationContext.getBean("colorFactoryBean");
    Object bean2 = applicationContext.getBean("colorFactoryBean");

    System.out.println(bean1);
    System.out.println(bean2.getClass());//class com.atguigu.bean.Color
    System.out.println(bean1==bean2);
  }

  private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String name:beanDefinitionNames) {
      System.out.println(name);
    }
  }

测试结果

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female
colorFactoryBean
rainbow
color factory generate a instance
color factory generate a instance
com.atguigu.bean.Color@79c97cb
class com.atguigu.bean.Color
false


http://lihuaxi.xjx100.cn/news/1393930.html

相关文章

视频怎么加水印?这几种加水印方法非常简单

给视频加水印是一种保护知识产权的方法。水印是一种数字标记&#xff0c;可以包括作者的名称、品牌标识或其他信息&#xff0c;以便识别和追踪视频的来源。通过给视频加水印&#xff0c;能够有效地防止视频被盗用或未经授权的使用&#xff0c;让我们的知识产权得到更好的保护。…

一篇文章帮你弄懂邻接矩阵,邻接表和链式前向星的区别

前言&#xff1a; 在学C的时候&#xff0c;面对各种各样的存图方式&#xff0c;脑子都大了不少&#xff0c;各种算法还在向我冲来&#xff0c;结果一个邻接矩阵/邻接表/链表轻松给了我一下暴击就直接让我KO了&#xff0c;趁着脑子还算清楚&#xff0c;详细的介绍下这三种存图方…

多模块Springboot项目maven单独打包子模块

背景介绍 最近接手一个项目代号XXL&#xff0c;是一个多模块的Springboot项目&#xff0c;在解决了线上的bug之后&#xff0c;想单独给子模块打包上线部署&#xff0c;问题来了。如果整个工程一起mvn -X -DskipTests clean package&#xff0c;打包出来的XXL-web.jar是可以正常…

小程序反馈与投诉混淆官方修改指引

根据《微信小程序平台运营规范》5.14“混淆行为&#xff1a;5.14.1 恶意混淆腾讯官方功能”&#xff0c;相关违规类型包括但不限于以下类型。 官方“反馈与投诉”入口与样式&#xff1a; 违规类型1&#xff1a;混淆官方投诉入口 小程序中的投诉入口样式与官方投诉入口icon名称…

设计模式思考,简单工厂模式和策略模式的区别?

最近学习了设计模式&#xff0c;学到简单工厂模式和策略模式的时候想&#xff0c;这两个模式不是一样嘛&#xff0c;仔细思考之后发现大体设计思路是一样的&#xff0c;但是细节却有所不一样。 简单工厂模式 简单工厂模式是一种创建型设计模式&#xff0c;它主要涉及对象的创建…

集合框架、多线程、IO流

目录 集合框架 Java迭代器&#xff08;Iterator&#xff09; Java集合类 Collection派生 Map接口派生&#xff1a; Java集合List ArrayList Vector LinkedList Java集合Set HashSet LinkedHashSet TreeSet Java集合Queue&#xff08;队列&#xff09; PriorityQue…

HbuilderX运行时遇见文件找不到问题

错误类型 解决方法 找到报错的文件 系统提示crypto-js 和 sm-crypto 找不到&#xff0c;然后注释掉找不到的文件 运行成功&#xff01;&#xff01;&#xff01;

Java开发工具MyEclipse发布v2023.1.2,今年第二个修复版!

MyEclipse一次性提供了巨量的Eclipse插件库&#xff0c;无需学习任何新的开发语言和工具&#xff0c;便可在一体化的IDE下进行Java EE、Web和PhoneGap移动应用的开发&#xff1b;强大的智能代码补齐功能&#xff0c;让企业开发化繁为简。 MyEclipse v2023.1.2官方正式版下载 …