Spring注解开发详细教程(二)

简介: 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);
}

运行结果:

1568c1a6c5f046d58909cb17b17fdad8.png


当在类上使用时表示:

对类中组件统一设置,满足当前条件,这个类中配置的所有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);
    }
}

运行结果:

6b1045f1ac8141e79290e2188210cdd9.png

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

运行结果:

f98e6cd7450d46a88aa024955f1897d6.png

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

运行结果:

395eddb05e0740519a102780a9834baf.png

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

运行结果:

dd87d27d342b4d34a14511c37fdd2fc5.png

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

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

当是单实例时:

bfe317c17f1643598b9313bcb8c74498.png

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

运行结果:

ad4897f0cd9b4af4b943d49ca279aea0.png

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

测试:

ebdc51f73aa84283a91ffcf82e89d247.png



相关文章
|
13天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
34 0
|
1月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
|
20天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
43 4
SpringBoot必须掌握的常用注解!
|
11天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
22 2
|
22天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
75 2
|
22天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
34 1
|
29天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
68 2
|
1月前
|
XML Java 数据格式
提升效率!Spring Boot 开发中的常见失误轻松规避
本文深入探讨了在 Spring Boot 开发中常见的失误,包括不当使用注解、不良异常处理、低效日志记录等,提供了有效的规避策略,帮助开发者提升代码质量和系统性能,构建更健壮、高效的应用程序。
|
16天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
30 0
|
17天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
12 0
下一篇
无影云桌面