首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring注解驱动

Spring注解驱动

作者头像
Java微观世界
发布2025-01-20 21:45:42
发布2025-01-20 21:45:42
14100
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行

1、@Configuration配置类

@Configuration(proxyBeanMethods = true)

  • 默认true,表示被@Bean标识的方法都会被cglib进行代理,会走bean生命周期的行为,如@postConstruct
  • 在同一个configuration中调用@Bean标识的方法,无论调用几次都是同一个bean,这个bean只创建一次

@Configuration(proxyBeanMethods = false)

  • false表示被@Bean标识的方法都不会被cglib进行代理,不会走bean生命周期的行为
  • 在同一个configuration中调用@Bean标识的方法,就只是普通方法的执行而已,并不会从容器中获取对象,调用多次,创建多个对象

组件类

代码语言:javascript
代码运行次数:0
运行
复制
//用户类
public class User {
    private Pet pet;

    public User(Pet pet) {
        this.pet = pet;
    }

    public Pet getPet() {
        return pet;
    }

    @PostConstruct
    public void init() {
        System.out.println("user  初始化。。。");
    }
}
//宠物类
public class Pet {
    @PostConstruct
    public void init() {
        System.out.println("pet 初始化。。。");
    }
}

配置类

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration(proxyBeanMethods = true)
public class MyConfig {
    @Bean
    public User user(){
        Pet pet = pet();
        Pet pet1 = pet();
        return new User(pet);
    }
    @Bean
    public Pet pet(){
        return new Pet();
    }
}

启动类

代码语言:javascript
代码运行次数:0
运行
复制
@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        //获取ioc容器
        ConfigurableApplicationContext context = 
        SpringApplication.run(SpringbootApplication.class, args);
        //获取组件
        User user1 = context.getBean("user", User.class);
        User user2 = context.getBean("user", User.class);
        Pet pet1 = context.getBean("pet", Pet.class);
        Pet pet2 = context.getBean("pet", Pet.class);

        System.out.println(user1==user2);
        System.out.println(pet1==pet2);
        System.out.println(user1.getPet()==pet1);
    }
}

当proxyBeanMethods =true

  • 在同一个Configuration中pet和pet1对象实例为同一个
  • pet进行了一次初始化
  • 容器中多次获取组件都是同一个对象实例

当proxyBeanMethods =false

  • 在同一个Configuration中pet和pet1为不同的对象实例( idea也会警告飘红)
  • pet没有走bean的初始化方法,只是简单调用new 新对象
  • Configuration中获取实例非单例,但是ioc容器中依然是单例
  • user中的pet是在configration中获取的对象,pet1也是从configration中获取的,分别创建了两个对象

所以,如果配置类中的@Bean标识的方法之间不存在依赖调用的话,可以设置为false,可以避免拦截方法进行代理操作,也是提升性能的一种优化。但是需要注意,@Bean标识的返回值对象还是会放入到容器中的,从容器中获取bean还是可以是单例的,会走生命周期。

2、@Scope设置组件作用域

  • prototype:多例,ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象。
  • singleton:单例(默认值),ioc容器启动会调用方法创建对象方到容器中。每次获取就是直接从容器中拿。
  • request:同一次请求创建一个实例
  • session:同一个session创建一个实例
代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
public class MainConfig {
    @Bean
    @Scope(value = "prototype")
    public Person person(){
        return new Person(1,"张三");
    }
}

2、@Lazy懒加载

  • 单例bean:默认ioc容器启动的时候创建对象
  • 懒加载bean:ioc容器启动不创建对象。第一次使用(获取)bean时候创建对象,只创建一次
代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
public class MainConfig {
    @Bean
    @Lazy
    public Person person(){
        return new Person(1,"张三");
    }
}

3、@Conditional按照条件加载bean

  • 注释在方法:windows系统加载李雷,linux系统加载韩梅梅
  • 注释在类上:满足条件整个类才会配置加载bean
代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
public class MainConfig {
    @Conditional({WindowsCondition.class})
    @Bean("lilei")
    public Person person01(){
        return new Person(10,"李雷");
    }
    @Conditional({LinuxCondition.class})
    @Bean("hanmeimei")
    public Person person02(){
        return new Person(20,"韩梅梅");
    }
}

加载条件

代码语言:javascript
代码运行次数:0
运行
复制
//判断是否linux系统
public class LinuxCondition implements Condition {
    /**
     *ConditionContext:判断条件能使用的上下文
     *AnnotatedTypeMetadata:注释信息
     */
    @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();
        //linux返回true,否则返回false
        String property = environment.getProperty("os.name");
        return property.contains("linux") ? true : false;
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
//判断是否windows系统
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //linux返回true,否则返回false
        String property = context.getEnvironment().getProperty("os.name");
        return property.contains("Windows") ? true : false;
    }
}

4、@Import为容器添加组件

  • 传统方式:包扫描+组件标注注解(@Controller等)
  • @Bean:导入第三方包里面的组件
1)@Import

容器中自动注册组件,id默认全类名

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
@Import({Red.class, Blue.class})
public class MainConfig {
}

打印ioc容器中所有组件

代码语言:javascript
代码运行次数:0
运行
复制
public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        for (String beanName : context.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }
    }
}

结果:

代码语言:javascript
代码运行次数:0
运行
复制
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
spring.module.annotation.entity.Red
spring.module.annotation.entity.Blue
2)@ImprotSelector

返回多个组件的全类名数组

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
@Import({MyImportSelector.class})
public class MainConfig {
}

自定义逻辑返回需要导入的组件

代码语言:javascript
代码运行次数:0
运行
复制
public class MyImportSelector implements ImportSelector {
    /**
     * 返回值:导入容器的组件数组,id为全类名
     *AnnotationMetadata:标注此注解的类上面的所有注解信息
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"spring.module.annotation.entity.Black", "spring.module.annotation.entity.Yellow"};
    }
}

三个注解信息分别为:@Configuration、@ComponentScan、@Import

结果:

代码语言:javascript
代码运行次数:0
运行
复制
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
spring.module.annotation.entity.Black
spring.module.annotation.entity.Yellow
3)@ImprotBeanDefinitionRegistrar

手动注册bean到容器中

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@ComponentScan("spring.module.annotation")
@Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}

自定义手工注册

代码语言:javascript
代码运行次数:0
运行
复制
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * AnnotationMetadata:此注解类的所有注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     *      通过BeanDefinitionRegistry.registerBeanDefinition手工注册bean
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        boolean exist = registry.containsBeanDefinition("spring.module.annotation.entity.Black");
        //如果存在Black的bean,则会注册White的bean
        if(exist){
            //指定bean名
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(White.class);
            registry.registerBeanDefinition("white",rootBeanDefinition);
        }

    }
}

结果:

代码语言:javascript
代码运行次数:0
运行
复制
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
spring.module.annotation.entity.Black
spring.module.annotation.entity.Yellow
white

5、@Value赋值

  1. 基本数值
  2. 可以写#{};如#{5-2}
  3. 可以写${};取出配置文件properties中的值

6、@PropertySource加载外部配置文件

代码语言:javascript
代码运行次数:0
运行
复制
@PropertySource(value={"classpath:/jdbc.properties"})
@Configuration
public class MyConfig(){
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、@Configuration配置类
  • 2、@Scope设置组件作用域
    • 2、@Lazy懒加载
    • 3、@Conditional按照条件加载bean
    • 4、@Import为容器添加组件
      • 1)@Import
      • 2)@ImprotSelector
      • 3)@ImprotBeanDefinitionRegistrar
    • 5、@Value赋值
    • 6、@PropertySource加载外部配置文件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档