栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

二、底层注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

二、底层注解

二、底层注解

目录
  • 二、底层注解
    • 2.1 容器功能
      • 2.1.1. @Configuration
        • 2.2.1.1. 基本使用
        • 2.2.1.2. 全模式(Full Mode)和轻量级模式(Lite Mode)
        • 2.2.1.3. 其他同类型注解
      • 2.1.2. @import
        • 2.2.1.1. 基本使用
      • 2.1.3. @Conditional
      • 2.1.4. @importResource
      • 2.1.5. @ConfigurationProperties
        • 2.1.5.1. @Component + @ConfigurationProperties
        • 2.1.5.1. @ConfigurationProperties

2.1 容器功能 2.1.1. @Configuration 2.2.1.1. 基本使用

User.java

package cn.com.springboot.demo.bean;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;


@Setter
@Getter
@ToString
@NoArgsConstructor
public class User {

    
    private String name;

    
    private String age;

    public User(String name, String age) {
        this.name = name;
        this.age = age;
    }
}

Pet.java

package cn.com.springboot.demo.bean;

import lombok.*;


@Setter
@Getter
@ToString
@NoArgsConstructor
public class Pet {

    
    private String breed;

    
    private String petName;

    public Pet(String breed, String petName) {
        this.breed = breed;
        this.petName = petName;
    }
}

MyConfig01.java

package cn.com.springboot.demo.config;

import cn.com.springboot.demo.bean.Pet;
import cn.com.springboot.demo.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyConfig01 {

    
    @Bean
    public User user01() {
        return new User("张三", "27");
    }

    
    @Bean("myPet")
    public Pet pet01() {
        return new Pet("cat", "27");
    }
}

  • @Configuration:告诉 spring-boot 这是一个配置类,也就是配置文件
  • @Bean:将该方法注册为一个组件,添加到容器中
  • 组件 ID:方法名就是这个组件的组件 ID
  • 返回值:组件在容器中实例
  • @Bean(“myPet”):定义 ID 为 myPet 的组件
  • 配置类本身也是一个组件
  • 注册的组件,默认是单实例的

MainApp.java

package cn.com.springboot.demo;

import cn.com.springboot.demo.bean.Pet;
import cn.com.springboot.demo.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);

        User user01 = run.getBean("user01", User.class);
        Pet myPet = run.getBean("myPet", Pet.class);

        System.out.println(user01);
        System.out.println(myPet);
    }
}

运行结果

User(name=张三, age=27)
Pet(breed=cat, petName=27)
2.2.1.2. 全模式(Full Mode)和轻量级模式(Lite Mode)

@Configuration 注解在 spring-boot 2 中多了以下的属性:

...
boolean proxyBeanMethods() default true;
...

默认值是 true 。如果 @Configuration(proxyBeanMethods = true) ,那么则是使用代理对象调用方法。spring-boot 总会检查这个组件是否存在容器中,如果存在则返回该组件,以此保证组件的单实例。如果 @Configuration(proxyBeanMethods = false),则会跳过上述检查,每次在调用组件时,都会返回新的组件。

  • Full Mode: proxyBeanMethods = true
    • 配置的组件如果有依赖关系,方法调用单实例组件
  • Lite Mode:proxyBeanMethods = false
    • 配置的组件如果没有依赖关系,跳过检查过程,加速容器启动

示例代码

proxyBeanMethods = true 的情况:

MyConfig01.java

package cn.com.springboot.demo.config;

import cn.com.springboot.demo.bean.Pet;
import cn.com.springboot.demo.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration(proxyBeanMethods = true)
public class MyConfig01 {

    
    @Bean
    public User user01() {
        return new User("张三", "27");
    }

    
    @Bean("myPet")
    public Pet pet01() {
        return new Pet("cat", "27");
    }
}

MainApp.java

package cn.com.springboot.demo;

import cn.com.springboot.demo.bean.User;
import cn.com.springboot.demo.config.MyConfig01;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);

        // 测试 MyConfig01 的 Full Mode 和 Lite Mode
        MyConfig01 bean = run.getBean(MyConfig01.class);
        User user01 = bean.user01();
        User user02 = bean.user01();
        System.out.println("Full Mode:" + (user01 == user02));
    }
}

运行结果

Full Mode:true

proxyBeanMethods = false 的情况:

MyConfig01.java

package cn.com.springboot.demo.config;

import cn.com.springboot.demo.bean.Pet;
import cn.com.springboot.demo.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration(proxyBeanMethods = false)
public class MyConfig01 {

    
    @Bean
    public User user01() {
        return new User("张三", "27");
    }

    
    @Bean("myPet")
    public Pet pet01() {
        return new Pet("cat", "27");
    }
}

MainApp.java

package cn.com.springboot.demo;

import cn.com.springboot.demo.bean.User;
import cn.com.springboot.demo.config.MyConfig01;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);

        // 测试 MyConfig01 的 Full Mode 和 Lite Mode
        MyConfig01 bean = run.getBean(MyConfig01.class);
        User user01 = bean.user01();
        User user02 = bean.user01();
//        System.out.println("Full Mode:" + (user01 == user02));
        System.out.println("Lite Mode:" + (user01 == user02));
    }
}

运行结果

Lite Mode:false
2.2.1.3. 其他同类型注解

以前用于注册组件的注解也是可以使用的,如:

@Component          // 泛指组件,将该组件交给 Spring 管理
@Controller         // 作用于 controller 上,将该组件交给 Spring 管理
@Service            // 作用于逻辑实现类上,将该实现类交给 Spring 管理
@Repository         // 作用于持久层的接口上,将该接口的实现类交给 Spring 管理
@ComponentScan      // 定义包扫描规则
2.1.2. @import 2.2.1.1. 基本使用

通过调用指定类的无参构造,将指定类型的组件导入到容器中,可以使用数组传递多个。如:

示例

MyConfig01.java

package cn.com.springboot.demo.config;



import ch.qos.logback.core.db.DBHelper;
import cn.com.springboot.demo.bean.User;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;

@import({User.class, DBHelper.class})
@Configuration
public class MyConfig02 {}

MainApp.java

package cn.com.springboot.demo;

import ch.qos.logback.core.db.DBHelper;
import cn.com.springboot.demo.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Arrays;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);

        // 测试 MyConfig01 的 Full Mode 和 Lite Mode
//        MyConfig01 bean = run.getBean(MyConfig01.class);
//        User user01 = bean.user01();
//        User user02 = bean.user01();
//        System.out.println("Full Mode:" + (user01 == user02));
//        System.out.println("Lite Mode:" + (user01 == user02));
//        System.out.println("---------------------------------------");

        String[] beans = run.getBeanNamesForType(User.class);
        Arrays.asList(beans).forEach(System.out::println);

        String[] beans2 = run.getBeanNamesForType(DBHelper.class);
        Arrays.asList(beans2).forEach(System.out::println);
    }
}

运行结果

cn.com.springboot.demo.bean.User
ch.qos.logback.core.db.DBHelper
  • @import 导入组件的默认名字:全类名
    • 例:ch.qos.logback.core.db.DBHelper
2.1.3. @Conditional

满足一定的条件时,才向容器中注入组件。@Conditional 存在很多派生注解,如:

派生注解名说明
ConditionalOnWebApplication当前项目是Web项目
ConditionalOnJava基于 Java 版本
ConditionalOnJndi基于 JNDI 存在
ConditionalOnWarDeployment当应用程序为传统 WAR 部署
ConditionalOnSingleCandidate当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选Bean
ConditionalOnProperty指定的属性是否有指定的值
Profile指定的 Profile 被激活
ConditionalOnMissingBean当容器里没有指定 Bean
ConditionalOnCloudPlatform当指定的云平台处于活动状态
ConditionalOnClass当类路径下有指定类
ConditionalOnMissingClass当类路径下没有指定类
ConditionalOnResource类路径是否有指定的值
ConditionalOnRepositoryType已启用的特定类型的 Spring 数据仓库
ConditionalOnNotWebApplication当前项目不是Web项目
ConditionalOnBean当容器里有指定 Bean
ConditionalOnDefaultWebSecurityWeb Security 可用并且用户没有自定义配置
ConditionalOnEnabledResourceChain检查Spring资源处理链是否启用。匹配WebProperties.Resources.Chain.getEnabled()是否为真,或者webjar -locator-core是否在类路径上
ConditionalOnexpression基于 SpEL 表达式

示例(ConditionalOnBean,当存在 pet03 时,才向容器中添加 user01)

MyConfig03.java

package cn.com.springboot.demo.config;

import cn.com.springboot.demo.bean.Pet;
import cn.com.springboot.demo.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyConfig03 {

    
    @ConditionalOnBean(name = "pet01")
    @Bean
    public User user03() {
        return new User("张三", "27");
    }

    
    @Bean("pet")
    public Pet pet03() {
        return new Pet("cat", "coco");
    }
}

MainApp.java

package cn.com.springboot.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);

        // 测试 MyConfig03 的 @ConditionalOnBean
        System.out.println(run.containsBean("user03"));
    }
}

运行结果

false
  • @ConditionalOnBean(name = “pet01”) 可以加在方法上也可以加在类上
    • 方法上:当条件不满足时,只有当前方法不会注册
    • 类上:当条件不满足时,整个类中的组件都不会注册
2.1.4. @importResource

导入原生的配置文件。如果之前就存在使用 XML 配置组件的方式或者第三方使用 XML 配置的组件方式,需要向项目中导入此类配置时使用。如:

示例

beans.xml




    
        
        
    

    
        
        
    

Myconfig04.java

package cn.com.springboot.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.importResource;


@Configuration
@importResource("classpath:beans.xml")
public class MyConfig04 {}

MainApp.java

package cn.com.springboot.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args);
        
        // 测试 MyConfig04 的 @importResources
        System.out.println(run.containsBean("user04"));
        System.out.println(run.containsBean("pet04"));
    }
}

运行结果

true
true
2.1.5. @ConfigurationProperties

配置绑定。在开发中一般将一些变化的东西写在 properties 文件中。如,DB连接信息等。

2.1.5.1. @Component + @ConfigurationProperties

示例

Car.java

package cn.com.springboot.demo.bean;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Setter
@Getter
@ToString
@NoArgsConstructor
@Component
@ConfigurationProperties("car01")
public class Car {

    
    private String brand;

    
    private String price;

    public Car(String brand, String price) {
        this.brand = brand;
        this.price = price;
    }
}

application.properties

car01.brand=BMW
car01.price=1200000

CarController.java

package cn.com.springboot.demo.controller;

import cn.com.springboot.demo.bean.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CarController {

    @Autowired
    private Car car;

    @RequestMapping("/car")
    public Car myCar() {
        return car;
    }
}

运行结果

  • @Component:将 Car 注册为一个组件,才能拥有 spring-boot 提供的功能
  • @ConfigurationProperties:指定配置文件的前缀
2.1.5.1. @ConfigurationProperties

示例

Car.java

package cn.com.springboot.demo.bean;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;


@Setter
@Getter
@ToString
@NoArgsConstructor
// @Component
@ConfigurationProperties("car02")
public class Car {

    
    private String brand;

    
    private String price;

    public Car(String brand, String price) {
        this.brand = brand;
        this.price = price;
    }
}

application.properties

car02.brand=LEXUS
car02.price=1800000

CarController.java

package cn.com.springboot.demo.controller;

import cn.com.springboot.demo.bean.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CarController {

    @Autowired
    private Car car;

    @RequestMapping("/car")
    public Car myCar() {
        return car;
    }
}

MyConfig05.java

package cn.com.springboot.demo.config;

import cn.com.springboot.demo.bean.Car;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;


@Configuration
@EnableConfigurationProperties(Car.class)
public class MyConfig05 {}

运行结果

  • @ConfigurationProperties:指定配置文件的前缀
  • @EnableConfigurationProperties(${value}):
    • 开启指定 ${value} 的配置绑定功能
    • 将 ${value} 组件注册到容器中
    • 必须写在配置类上
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/295308.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号