爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      Spring注解开发详细教程

      首页 知识中心 软件开发 文章详情页

      Spring注解开发详细教程

      2023-06-15 06:37:58 阅读次数:472

      Bean,spring,springmvc

      Spring注解开发详细教程 (配合雷神的视频)

      一、AnnotationConfigApplicationContext

      1.配置类

      1.1使用传统xml方式

      applicationContext.xml:

      <bean id="person" class="com.rg.domain.Person" >
          <property name="name" value="张三"/>
          <property name="age" value="19"/>
      </bean>
      

      person类:

      package com.rg.domain;
      
      public class Person {
          private String name;
          private Integer age;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          public Person(String name, Integer age) {
              this.name = name;
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      }
      

      测试类:

      @Test
      public void test01(){
          //加载配置文件
          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
          Person person = (Person) applicationContext.getBean("person");//通过id获取实体
          System.out.println(person);
      }
      

      1.2使用配置类方式:

      MainConfig 配置类

      //配置类==配置文件
      @Configuration //告诉Spring这是一个配置类
      public class MainConfig {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person") //修改方法名称
          public Person person(){
              return new Person("lisi",20);
          }
      }
      

      测试类

      @Test
      public void test02(){
          ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
          Person person = applicationContext.getBean(Person.class);//通过类名来获取
          System.out.println(person);
      }
      

      2.包扫描

      2.1传统xml方式:

      <!--包扫描,只要标注了@Controller,@service,@Repository,@Component 类对象就会被自动加载到IOC容器中-->
      <context:component-scan base-package="com.rg"/>
      

      2.2注解方式:

      MainConfig配置类

      //配置类==配置文件
      @Configuration //告诉Spring这是一个配置类
      @ComponentScan("com.rg")
      public class MainConfig {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person") //修改方法名称
          public Person person(){
              return new Person("lisi",20);
          }
      }
      

      项目结构:

      Spring注解开发详细教程

      其中controller,dao,service中的类均使用相对应的注解.

      测试类:

      @Test
      public void test03(){
          ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
          String[] names = applicationContext.getBeanDefinitionNames();//获取容器中所有的对象名称
          for (String name : names) {
              System.out.println(name);
          }
      }
      

      运行结果:

      Spring注解开发详细教程

      二、组件添加

      1.@ComponentScan

      1.1传统xml

      <!--包扫描,只要标注了@Controller,@service,@Repository,@Component 类对象就会被自动加载到IOC容器中-->
      <context:component-scan base-package="com.rg" use-default-filters="false">
           <!--use-default-filters : 是否使用默认的过滤器,默认值true 扫描包中的全部文件-->
      	 <!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->
          type可为regex (正则),annotation(注解),assignable(接口或类)
          
         <context:exclude-filter type="assignable" expression="com.rg.controller.BookController"/>
              <context:include-filter type="assignable" expression="com.rg.service.BookService"/>
          
      </context:component-scan>
      

      1.2使用配置类

      1.2.1ComponentScan注解的基本使用
      //配置类==配置文件
      @Configuration //告诉Spring这是一个配置类
      
      //JDK8之后可以写多个ComponentScan;如果不是该版本则可 使用ComponentScans属性
      //注意
      @ComponentScan(value="com.rg",includeFilters = {
              @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class})},
              useDefaultFilters = false)
      
      @ComponentScans(
              value = {
                      @ComponentScan(value="com.rg",includeFilters = {
                              @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class}),//第一个过滤器,根据注解类型
                      @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}),//根据给定的类型
                      },
                       useDefaultFilters = false),
                      @ComponentScan(),
                      //...
              }
      )
      //@ComponentScan  value:指定要扫描的包
      //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
      //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
      //FilterType.ANNOTATION:按照注解
      //FilterType.ASSIGNABLE_TYPE:按照给定的类型;
      //FilterType.ASPECTJ:使用ASPECTJ表达式
      //FilterType.REGEX:使用正则指定
      //FilterType.CUSTOM:使用自定义规则
      public class MainConfig {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person") //修改方法名称
          public Person person(){
              return new Person("lisi",20);
          }
      }
      

      测试结果(测试类和上一个相同):

      只有Controller包和service包中创建的对象

      Spring注解开发详细教程

      注意: pom.xml中的

      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      

      控制的是编译使用的JDK版本,如果此处使用的是JDK7,则MainConfig上无法添加多个@ComponentScan.

      1.2.2自定义过滤器

      在config包中创建MyTypeFilter类,并继承TypeFilter接口,写过滤条件.

      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();
              String className = classMetadata.getClassName();//获取当前的类名
              System.out.println("-->" + className);
              if (className.contains("er")) {//如果类名包含er
                  return true;//被过滤器过滤
              }
              return false;//不被过滤
          }
      }
      

      MainConfig中引入:

      @ComponentScan(value="com.rg",includeFilters = {
              // @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
              // @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}),
              @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
              }, useDefaultFilters = false)
      @Configuration //告诉Spring这是一个配置类
      public class MainConfig {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person") //修改方法名称
          public Person person(){
              return new Person("lisi",20);
          }
      }
      

      测试结果:

      第一部分是符合条件的类名称,第二部分是存入到IOC容器中的对象的名称.

      Spring注解开发详细教程

      2.@Scope

      MainConfig:

      //默认是单实例的
      /**
       * * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
       * * @see ConfigurableBeanFactory#SCOPE_SINGLETON
       * * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
       * * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
      
       * @return\
       * @Scope:调整作用域
       * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
       *                 每次获取的时候才会调用方法创建对象;
       * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。
       *           以后每次获取就是直接从容器(map.get())中拿,
       * request:同一次请求创建一个实例
       * session:同一个session创建一个实例
       *
       * 懒加载:
       *        单实例bean:默认在容器启动的时候创建对象;
       *        懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
       *
       */
      @Scope( )
      @Configuration
      public class MainConfig2 {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person")
          public Person person(){
              System.out.println("给容器中添加Person...");
              return new Person("lisi",20);
          }
      }
      

      测试:

      @Test
      public void test04(){
      
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
          //System.out.println("IOC容器创建完成...");
          //System.out.println("hahha嗷嗷嗷");
          //   Person person = (Person) applicationContext.getBean("person");
          //  Person person2 = (Person) applicationContext.getBean("person");
          //  System.out.println(person == person2); //当为默认时,结果为true,当为prototype结果为false.
      
      
      }
      

      运行结果:

      Spring注解开发详细教程

      当修改为@Scope(“propotype”)时,会先创建IOC容器,然后每次获取才调方法,创对象.
      Spring注解开发详细教程

      注:此处会出现@Scope(“propotype”)失效的问题,解决办法还没有找到…

      3.@Lazy

      单实例bean:默认在容器启动的时候创建对象;

      懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化.

      MainConfig

      @Lazy
      @Scope
      @Configuration
      public class MainConfig2 {
          //给容器注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
          @Bean("person")
          public Person person(){
              System.out.println("给容器中添加Person...");
              return new Person("lisi",20);
          }
      }
      

      测试:

      @Test
      public void test04(){
      
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
          System.out.println("IOC容器创建完成...");
          //System.out.println("hahha嗷嗷嗷");
             Person person = (Person) applicationContext.getBean("person");
           Person person2 = (Person) applicationContext.getBean("person");
           System.out.println(person == person2);
      
      
      }
      

      测试结果:

      Spring注解开发详细教程

      4.@Conditional

      按照一定的条件进行判断,满足条件给容器中注册bean;

      例:

      • 如果系统是windows,给容器中注册(“bill”)
      • 如果是linux系统,给容器中注册(“linus”)

      创建LinuxCondition,WindowsCondition并实现Condition接口.

      LinuxCondition

      //判断是否是Linux系统
      public class LinuxCondition implements Condition {
          /**
           *
           * @param context 判断条件使用的上下文(环境)
           * @param metadata :注释信息
           * @return
           */
          @Override
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              //1.获取IOC使用的BeanFactory
              ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
              //2.获取类加载器
              ClassLoader classLoader = context.getClassLoader();
              //3.获取当前环境信息
              Environment environment = context.getEnvironment();
              //4.获取Bean定义的注册类
              BeanDefinitionRegistry registry = context.getRegistry();
      
              String property = environment.getProperty("os.name");
      
              //可以判断容器中的Bean注册情况,也可以给容器中注册Bean
              if(property.contains("linux")){
                  return true;
              }
      
      
              return false;
          }
      }
      

      WindowsCondition

      //判断是否是windows系统
      public class WindowsCondition implements Condition {
          @Override
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              Environment environment = context.getEnvironment();
              String property = environment.getProperty("os.name");
              if(property.contains("Windows")){
                  return true;
              }
              return false;
          }
      }
      

      MainConfig

      //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
      //@Conditional({WindowsCondition.class})
      @Configuration
      public class MainConfig3 {
      
      
          /**
           * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
           *
           * 如果系统是windows,给容器中注册("bill")
           * 如果是linux系统,给容器中注册("linus")
           */
          @Conditional({WindowsCondition.class})
          @Bean("bill")
          public Person person01(){
              return new Person("Bill Gates",62);
          }
      
          @Conditional({LinuxCondition.class})
          @Bean("linus")
          public Person person02(){
              return new Person("linus",48);
          }
          
      }
      

      测试:

      @Test
      public void test05() {
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
          String[] names = applicationContext.getBeanNamesForType(Person.class);
          //获取系统环境配置对象
          ConfigurableEnvironment environment = applicationContext.getEnvironment();
          //动态获取环境变量
          String property = environment.getProperty("os.name");
          System.out.println(property);
          for (String name : names) {
              System.out.println(name);
          }
          Map <String, Person> persons = applicationContext.getBeansOfType(Person.class);
          System.out.println(persons);
      
      }
      

      运行结果:

      Spring注解开发详细教程

      当在类上使用时表示:

      对类中组件统一设置,满足当前条件,这个类中配置的所有bean注册才能生效;

      5.@Import

      5.1 @Import(要导入的容器中的组件);

      容器中会自动注册这个组件,id默认是全类名.

      创建Color,Red类作为导入的组件.

      MainConfig

      //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
      @Conditional({WindowsCondition.class})
      @Configuration
      //@Import(value = Color.class)
      @Import({Color.class, Red.class})
      public class MainConfig4 {
      
          @Bean("person") //修改方法名称
          public Person person(){
              return new Person("lisi",20);
          }
      
          @Conditional({WindowsCondition.class})
          @Bean("bill")
          public Person person01(){
              return new Person("Bill Gates",62);
          }
      
          @Conditional({LinuxCondition.class})
          @Bean("linus")
          public Person person02(){
              return new Person("linus",48);
          }
      
      }
      

      测试:

      @Test
      public void test06() {
          ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig4.class);
          String[] names = applicationContext.getBeanDefinitionNames();//获取容器中所有的对象名称
          for (String name : names) {
              System.out.println(name);
          }
      
      }
      

      运行结果:

      Spring注解开发详细教程

      5.2 ImportSelector

      返回需要导入的组件的全类名数组;

      作用:批量注册Bean:

      编写MyInportSelector 实现ImportSelector接口

      public class MyInportSelector implements ImportSelector {
          @Override
          public String[] selectImports(AnnotationMetadata importingClassMetadata) {
              return new String[]{"com.rg.domain.Blue","com.rg.domain.Yellow"};
          }
      }
      

      MainConfig上添加注解:@Import({Color.class, Red.class, MyInportSelector.class})

      运行结果:

      Spring注解开发详细教程

      5.3 MyImportBeanDefinitionRegistrar

      手动注册bean到容器中(可以指定Bean的名称)

      创建MyImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口,编写注册的逻辑.

      public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
          /**
           * AnnotationMetadata:当前类的注解信息
           * BeanDefinitionRegistry:BeanDefinition注册类;
           * 		把所有需要添加到容器中的bean;调用
           * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来,可以指定名称.
           */
          @Override
          public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
              boolean definition = registry.containsBeanDefinition("com.rg.domain.Red");
              boolean definition2 = registry.containsBeanDefinition("com.rg.domain.Blue");
              if(definition && definition2){
                  //指定Bean定义信息;
                  RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
                  //注册一个Bean,指定Bean名
                  registry.registerBeanDefinition("rainBow",rootBeanDefinition);
              }
          }
      }
      

      MainConfig上添加注解:@Import({Color.class, Red.class, MyInportSelector.class, MyImportBeanDefinitionRegistrar.class})

      运行结果:

      Spring注解开发详细教程

      6.使用FactoryBean注册组件

      使用Spring提供的 FactoryBean(工厂Bean);
      1)、默认获取到的是工厂bean调用getObject创建的对象
      2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean

      创建ColorFactoryBean 实现FactoryBean接口

      //创建一个Spring定义的FactoryBean
      public class ColorFactoryBean implements FactoryBean<Color> {
          //返回一个Color对象,这个对象会添加到容器中
          @Override
          public Color getObject() throws Exception {
              System.out.println("ColorFactoryBean...getObject...");
              return new Color();
          }
      
          //返回对象的类型
          @Override
          public Class <?> getObjectType() {
              return Color.class;
          }
      
          //是否单例
          //true:这个bean是单例,在容器中保存一份
          //false:多例,每次获取都会创建一个新的Bean
          @Override
          public boolean isSingleton() {
              return false;
          }
      }
      
      

      编写MainConfig

      //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
      @Configuration
      public class MainConfig5 {
      
      
          // 使用Spring提供的 FactoryBean(工厂Bean);
          //1)、默认获取到的是工厂bean调用getObject创建的对象
          //2)、要获取工厂Bean本身,我们需要给id前面加一个&    &colorFactoryBean
      
          @Bean
          public ColorFactoryBean colorFactoryBean(){
              return new ColorFactoryBean();
          }
      
      }
      

      进行测试:

      @Test
      public void test07() {
          ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig5.class);
          //Bean 获取的是调用getObject创建的对象
          Object bean = applicationContext.getBean("colorFactoryBean");
          Object bean2 = applicationContext.getBean("colorFactoryBean");
          System.out.println("bean2 is Type:"+bean2.getClass());
          System.out.println(bean==bean2);
      
          Object bean3 = applicationContext.getBean("&colorFactoryBean");
          System.out.println(bean3.getClass());
      }
      

      运行结果:

      Spring注解开发详细教程

      &&小结:给容器中注册组件的四种方式

      1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]

      2)、@Bean[导入的第三方包里面的组件]

      3)、@Import[快速给容器中导入一个组件]

      • 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
      • 2)、ImportSelector:返回需要导入的组件的全类名数组

      4)、使用Spring提供的 FactoryBean(工厂Bean);

      •    1)、默认获取到的是工厂bean调用getObject创建的对象
        
      • 2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean

      7.生命周期

      7.1指定初始化和销毁方法

      通过@Bean指定init-method和destroy-method,相当于xml中的

      <bean id="person" class="com.rg.domain.Person"  init-method="XXX" destroy-method="XXX" >
      

      构造(对象创建)

      • 单实例:在容器启动的时候创建对象
      • 多实例:在每次获取的时候创建对象

      初始化: 对象创建完成并赋值好,调用初始化方法…

      销毁:

      • 单实例:容器关闭的时候
      • 多实例:容器不会管理这个Bean,容器不会调用销毁方法.

      ​

      编写MainConfigOfLifeCycle类

      @Configuration
      public class MainConfigOfLifeCycle {
          
          @Scope("prototype")
          @Bean(initMethod="init",destroyMethod = "destroy")
          public Car car(){
              return new Car();
          }
      }
      

      测试:

      @Test
      public void test01(){
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
          System.out.println("Container creation complete.....");
          applicationContext.getBean("car");
          //关闭容器
          applicationContext.close();
      }
      
      

      当是单实例时:

      Spring注解开发详细教程

      当是多实例时:

      Spring注解开发详细教程

      7.2定义初始化逻辑

      通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);

      创建Cat类并实现InitializingBean,DisposableBean接口.

      @Component
      public class Cat implements InitializingBean, DisposableBean {
      
          public Cat(){
              System.out.println("Cat constructor...");
          }
      
          @Override
          public void destroy() throws Exception {
              System.out.println("cat destroy...");
          }
      
          @Override
          public void afterPropertiesSet() throws Exception {
              System.out.println("cat afterPropertiesSet ...");
          }
      }
      

      MainConfigOfLifeCycle配置类

      @Configuration
      @ComponentScan("com.rg")
      public class MainConfigOfLifeCycle {
       	@Bean(initMethod="init",destroyMethod = "destroy")
          public Car car(){
              return new Car();
          }
      }
      
      @Test
      public void test01(){
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
          
          //关闭容器
          applicationContext.close();
      }
      

      运行结果:

      Spring注解开发详细教程

      7.3可以使用JSR250

      @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法

      @PreDestroy:在容器销毁bean之前通知我们进行清理工作

      创建Dog类:

      @Component
      public class Dog  {
          public Dog(){
              System.out.println("Dog constructor...");
          }
      
          //对象创建并赋值之后调用
          @PostConstruct
          public void init(){
              System.out.println("Dog PostConstruct...");
          }
      
          //容器移除对象之前
          @PreDestroy
          public void destroy(){
              System.out.println("Dog PreDestroy...");
          }
      }
      

      测试:

      Spring注解开发详细教程

      7.4BeanPostProcessor—bean的后置处理器

      在bean初始化前后进行一些处理工作;

      postProcessBeforeInitialization:在初始化之前工作

      postProcessAfterInitialization:在初始化之后工作

      创建MyBeanPostProcessor,实现BeanPostProcessor接口

      /**
       * 后置处理器:初始化前后进行处理工作
       * 将后置处理器加入到容器中
       */
      @Component
      public class MyBeanPostProcessor implements BeanPostProcessor{
      
      
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
              return bean;
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("postProcessAfterInitialization"+beanName+"=>"+bean);
              return bean;
          }
      
      
      }
      

      运行结果:

      Spring注解开发详细教程

      BeanPostProcessor原理

      populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
      initializeBean
      {
         applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
         invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
         applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
      }
      

      Spring底层对 BeanPostProcessor 的使用;

      bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;

      8.@Value

      作用:为属性赋值

      • 基本数值
      • 可以写SpEL:#{}
      • 可以写${};取出配置文件[properties]中的值(在运行环境变量中的值)

      Person类

      public class Person {
          //使用@Value赋值
          //1.基本数值
          //2.可以写SpEL:#{}
          //3.可以写${};取出配置文件[properties]中的值(在运行环境变量中的值)
      
          @Value("zhangsan")
          private String name;
          @Value("#{20+1}")
          private Integer age;
      
          @Value("${person.nickName}")
          private String nickName;
      
          public String getNickName() {
              return nickName;
          }
      
          public void setNickName(String nickName) {
              this.nickName = nickName;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          public Person(String name, Integer age) {
              this.name = name;
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      ", nickName='" + nickName + '\'' +
                      '}';
          }
      
          public Person(){
      
          }
      }
      

      MainConfig配置类:

      //使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
      @PropertySource(value = {"classpath:person.properties"})
      //@PropertySources(value = {@PropertySource({}),@PropertySource({})})
      @Configuration
      public class MainConfigOfPropertyValues {
          @Bean
          public Person person(){
              return new Person();
          }
      }
      

      测试

      @Test
      public void test08(){
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
          Person person = (Person) applicationContext.getBean("person");
          System.out.println(person);
      
          Environment environment = applicationContext.getEnvironment();
          String value = environment.getProperty("person.nickName");//通过environment也可以获取配置文件的属性值.
          System.out.println(value);
          applicationContext.close();
      }
      

      person.properties文件

      person.nickName=\u5C0F\u674E\u56DB
      

      运行结果:

      Spring注解开发详细教程

      9.自动装配

      Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;

      9.1@Autowired:自动注入

      1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值

      2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 applicationContext.getBean(“bookDao”)

      @Controller
      public class BookController {
          @Autowired
          private BookService bookService;
      }
      
      @Service
      public class BookService {
          @Autowired
          private BookDao bookDao;
      
          @Override
          public String toString() {
              return "BookService{" +
                      "bookDao=" + bookDao +
                      '}';
          }
      }
      
      // 默认是类名首字母小写
      @Repository
      public class BookDao {
          private String Label = "1";
      
          public String getLabel() {
              return Label;
          }
      
          public void setLabel(String label) {
              Label = label;
          }
      
          @Override
          public String toString() {
              return "BookDao{" +
                      "Label='" + Label + '\'' +
                      '}';
          }
      }
      
      @Configuration
      @ComponentScan({"com.rg.service","com.rg.dao","com.rg.controller"})
      public class MainConfigOfAutowired {
      
          @Bean("bookDao2")
          public BookDao bookDao(){
              BookDao bookDao = new BookDao();
              bookDao.setLabel("2");
              return bookDao;
          }
      }
      

      测试:

      @Test
       public void test01(){
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
          //获取BookService中注入的BookDao
          BookService bookService = applicationContext.getBean(BookService.class);
      
          //BookDao bean = applicationContext.getBean(BookDao.class);  当IOC容器中有多个对象时不能用类.class进行获取对象.
          //System.out.println(bean);
          System.out.println(bookService);
      }
      

      运行结果:

      IOC容器中有bookDao和bookDao2,因为@Autowired 下面的需要的名字为bookDao,所以里面注册的就是bookDao对象.如果改为bookDao2则里面注册的就是bookDao2对象.

      Spring注解开发详细教程

      3)、使用@Qualifier指定需要装配的组件的id,而不是默认使用属性名

      BookService{
      	  @Qualifier("bookDao2")	
            @Autowired
            BookDao  bookDao;
      }
      

      这样bookDao里面注册的就是bookDao2.

      4)、自动装配默认一定要将属性赋值好,没有就会报错;通过使用@Autowired(required=false); 可以当有的时候进行注册,没有的时候为null.

      BookService{
      	  @Qualifier("bookDao2")	
            @Autowired(required = false)
            BookDao  bookDao;
      }
      

      Spring注解开发详细教程

      5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;也可以继续使用@Qualifier指定需要装配的bean的名字

      BookService{
      	  //@Qualifier("bookDao2")	
            @Autowired(required = false)
            BookDao  bookDao;
      }
      
      @Repository
      public class BookDao {
          ......
      }
      
      
      @Configuration
      @ComponentScan({"com.rg.service","com.rg.dao","com.rg.controller"})
      public class MainConfigOfAutowired {
      
          @Primary
          @Bean("bookDao2")
          public BookDao bookDao(){
              BookDao bookDao = new BookDao();
              bookDao.setLabel("2");
              return bookDao;
          }
      }
      
      

      当没有Qualifier时, 为BookDao加上@Primary,则其优先权会升高,会优先注册该对象. 但如果此时有Qualifier,则由里面的名称决定.

      Spring注解开发详细教程

      6 )、扩展:Spring还支持使用@Resource(JSR250)和@Inject(JSR330) [java规范的注解]

      @Resource:

      •    可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
        
      • 没有能支持@Primary功能没有支持@Autowired(reqiured=false);
        

      @Inject:

      •    需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;支持@Primary
        

      @Autowired:Spring定义的规范; @Resource、@Inject都是java规范

      小结:

      @Autowired 当IOC容器中只有一个时,可以这样使用.此时由 待注册的名称决定.

      @Autowired经常和@Qualifier一起使用;此时,可以打破默认,由Qualifier指定的对象注册.

      @Autowired还可以和@Primary+其他组件注解(@Bean,@Service,@Controller…),从而提升其优先级,优先被使用.

      9.2 扩展:@Autowired使用的位置:

      @Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值

      1.放在参数位置

      1)、放在属性位置或setter方法上

      默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作

      @Component
      public class Car {
      	....
      }
      @Component
      public class Boss {
      
          //@Autowired:属性位置.
          private Car car;
          public Car getCar() {
              return car;
          }
      
          //标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值
          //方法使用的参数,自定义类型从IOC容器中获取.
          @Autowired//方法上
          public void setCar(Car car) {
              this.car = car;
          }
      
      }
      

      2 ) 、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取

      @Component
      public class Car {
      	....
      }
      @Component
      public class Boss {
      
          
          private Car car;
      
          @Autowired//可省略
          public Boss(Car car){
              this.car = car;
              System.out.println("Boss 有参构造器...");
          }
      
          public Car getCar() {
              return car;
          }
      
      
        
          public void setCar(Car car) {
              this.car = car;
          }
      
          @Override
          public String toString() {
              return "Boss{" +
                      "car=" + car +
                      '}';
          }
      }
      
      
      

      程序中:会自动调用有参构造为Boss中的Car进行赋值.IOC容器中的Car和Boss中的Car是同一个.

      3)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配

      @Bean
      @Autowired
      public Color color(Car car){
          Color color = new Color();
          color.setCar(car);
          return color;
      }
      

      注:参数卸载方法上或者 参数之前,或者省略都是可以的.

      9.3@Profile

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

      如:当开发环境时我们自动在环境中加入开发的相关组件,当是测试环境时,自动添加测试的相关组件,当是生成环境时,自动添加生产的组件.

      @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

      @Configuration
      @PropertySource("classpath:/jdbc.properties")
      public class MainConfigOfProfile implements EmbeddedValueResolverAware {
      
      
      
          private String driverClass;
          @Value("${jdbc.user}") // @value放在属性上
          private String user;
      
          @Override
          public void setEmbeddedValueResolver(StringValueResolver resolver) {
              //this.resolver = resolver;
              driverClass = resolver.resolveStringValue("${jdbc.driver}");
          }
      
          @Bean
          public Yellow yellow(){
              return new Yellow();
          }
      
          @Bean("prodDataSource")
          @Profile("prod")
          //@Profile("default")  @Value放在参数上
          public DataSource dataSourceProd(@Value("${jdbc.password}")String pwd) throws Exception {
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
              dataSource.setUser("root");
              dataSource.setPassword(pwd);
              dataSource.setJdbcUrl("jdbc:mysql:///goods");
              dataSource.setDriverClass(driverClass);
              return dataSource;
          }
      
          @Profile("test")
          @Bean("testDataSource")
          public DataSource dataSourceTest(@Value("${jdbc.password}")String pwd) throws Exception {
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
              dataSource.setUser("root");
              dataSource.setPassword(pwd);
              dataSource.setJdbcUrl("jdbc:mysql:///test");
              dataSource.setDriverClass(driverClass);
              return dataSource;
          }
      
          @Bean("devDataSource")
          @Profile("dev")
          public DataSource dataSourceDev(@Value("${jdbc.password}")String pwd) throws Exception {
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
              dataSource.setUser("root");
              dataSource.setPassword(pwd);
              dataSource.setJdbcUrl("jdbc:mysql:///travel");
              dataSource.setDriverClass(driverClass);
              return dataSource;
          }
      
      }
      
      

      补充:

      使用配置文件的两种方式:

      1. 使用@PropertySource(“classpath:/文件名称”),搭配@Value(“键”)
      2. 类实现EmbeddedValueResolverAware通过 resolver.resolveStringValue 获取键对应的值.

      测试:

      	 @Test
          public void test01(){
              //1.使用命令行动态参数,在Edit Configurations的VM options中加入 -Dspring.profiles.active=test
              //2.使用代码的方式激活某种环境
              //1.创建一个applicationContext
              AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
              //2.设置需要激活的环境
              //AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
             applicationContext.getEnvironment().setActiveProfiles("dev","test");
             //3.注册主配置类
             applicationContext.register(MainConfigOfProfile.class);
             //4.启动刷新容器
              applicationContext.refresh();
              String[] names = applicationContext.getBeanNamesForType(DataSource.class);
              System.out.println(names);
              for (String name : names) {
                  System.out.println(name);
              }
              applicationContext.close();
          }
      

      运行结果:

      Spring注解开发详细教程

      2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效

      如在类上加@Profile(“test”),使用的是开发环境,则里面的所有配置都无效.只有一致时才生效.

      3)、没有标注环境标识的bean在,任何环境下都是加载的;

      根据尚硅谷 雷神的<<Spring注解开发>> 整理总结

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/LXYDSF/article/details/119982615,作者:爱编程的大李子,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:SpringBoot Test Demo最常用的测试示范

      下一篇:关于SpringBoot中左侧边栏各图标的含义

      相关文章

      2025-05-12 10:19:12

      SpringBoot学习(6)(Bean对象扫描)(@ComponentScan)

      SpringBoot学习(6)(Bean对象扫描)(@ComponentScan)

      2025-05-12 10:19:12
      Bean , springboot , 启动 , 扫描 , 注解
      2025-05-08 09:03:21

      基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】

      本项目是一套基于spring+jsp+mysql实现的Java web论坛系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

      2025-05-08 09:03:21
      Java , jsp , spring , 功能 , 源码
      2025-05-08 09:03:07

      spring Bean的作用域和生命周期

      spring Bean的作用域和生命周期

      2025-05-08 09:03:07
      Bean , method , spring , 作用域 , 配置文件
      2025-05-07 09:08:54

      springboot系列教程(十二):基于转账案例,演示事务管理操作

      springboot系列教程(十二):基于转账案例,演示事务管理操作

      2025-05-07 09:08:54
      spring , 事务 , 接口 , 管理器 , 配置
      2025-05-07 09:07:56

      springmvc五种数据提交方式

      springmvc五种数据提交方式

      2025-05-07 09:07:56
      action , springmvc , 提交 , 数据 , 页面
      2025-05-06 09:19:12

      Spring的 Aop的完整实现流程?

      Spring的 Aop的完整实现流程?

      2025-05-06 09:19:12
      AOP , Bean
      2025-04-18 07:09:19

      深入理解Spring中的Bean循环依赖与解决机制

      Bean循环依赖是指两个或多个Bean之间相互依赖,形成依赖闭环的情况。例如,Bean A依赖Bean B,而Bean B又依赖Bean A。这种情况下,如果没有特殊处理,容器将无法正确初始化这些Bean,从而导致应用启动失败。

      2025-04-18 07:09:19
      Bean , Spring , 依赖 , 初始化 , 循环 , 缓存 , 解决
      2025-04-14 08:48:01

      Java注解实现之how to use path variable @PathVariable

      Java注解实现之how to use path variable @PathVariable

      2025-04-14 08:48:01
      Java , spring
      2025-04-14 08:45:36

      Java SpringBoot 应用使用命令行 mvn spring-boot run 启动的原理

      将应用程序打包为 jar 并使用嵌入式 HTTP 服务器的最大优势之一是可以像运行其他任何应用程序一样运行这些提供了 Web 功能的应用程序。 调试 Spring Boot 应用程序也很容易; 不需要任何特殊的 IDE 插件或扩展。

      2025-04-14 08:45:36
      jar , spring , 应用程序
      2025-04-09 09:11:38

      spring boot设置session超时时长(自定义spring boot session超时时长)

      spring boot设置session超时时长(自定义spring boot session超时时长)

      2025-04-09 09:11:38
      boot , session , spring , 设置 , 超时
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5237124

      查看更多

      最新文章

      SpringBoot学习(6)(Bean对象扫描)(@ComponentScan)

      2025-05-12 10:19:12

      基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】

      2025-05-08 09:03:21

      springboot系列教程(十二):基于转账案例,演示事务管理操作

      2025-05-07 09:08:54

      Spring的 Aop的完整实现流程?

      2025-05-06 09:19:12

      深入理解Spring中的Bean循环依赖与解决机制

      2025-04-18 07:09:19

      Java注解实现之how to use path variable @PathVariable

      2025-04-14 08:48:01

      查看更多

      热门文章

      SpringMVC的JSON处理及FastJSON的整合使用(七)

      2022-12-27 10:00:39

      Java(Spring拦截器、过滤器、AOP)

      2023-06-20 09:11:08

      基于XML的DI-为Spring配置多个子配置文件——平等关系

      2022-12-29 09:29:46

      Spring AOP-有接口的CGLIB动态代理

      2022-12-29 09:29:46

      基于注解的DI-Spring的JUnit4测试

      2022-12-29 09:29:46

      Spring5入门到实战------2、IOC容器底层原理

      2023-02-28 10:45:09

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      SpringBoot上传文件到后端服务器

      Spring 事务注解@Transaction日常用法

      Spring 与 JDBC

      解决 Cause: org.xml.sax.SAXParseException; lineNumber: 50; columnNumber: 21; 元素内容必须由格式正确的字符数据或标记组成的错误

      [springMVC学习]6、视图解析器,debug源码

      Java:从编程语言到编程思想

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号