Spring注解驱动

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 Spring注解驱动,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1、@Configuration配置类

@Configuration(proxyBeanMethods = true)

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

@Configuration(proxyBeanMethods = false)

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

组件类

//用户类
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 初始化。。。");
    }
}

配置类

@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();
    }
}

启动类

@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创建一个实例
@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时候创建对象,只创建一次
@Configuration
@ComponentScan("spring.module.annotation")
public class MainConfig {
    @Bean
    @Lazy
    public Person person(){
        return new Person(1,"张三");
    }
}

3、@Conditional按照条件加载bean

  • 注释在方法:windows系统加载李雷,linux系统加载韩梅梅
  • 注释在类上:满足条件整个类才会配置加载bean
@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,"韩梅梅");
    }
}

加载条件

//判断是否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;
    }
}
//判断是否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默认全类名

@Configuration
@ComponentScan("spring.module.annotation")
@Import({Red.class, Blue.class})
public class MainConfig {
}

打印ioc容器中所有组件

public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        for (String beanName : context.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }
    }
}

结果:

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

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

@Configuration
@ComponentScan("spring.module.annotation")
@Import({MyImportSelector.class})
public class MainConfig {
}

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

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
在这里插入图片描述

结果:

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到容器中

@Configuration
@ComponentScan("spring.module.annotation")
@Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}

自定义手工注册

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);
        }

    }
}

结果:

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加载外部配置文件

@PropertySource(value={"classpath:/jdbc.properties"})
@Configuration
public class MyConfig(){
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/148663.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!