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



相关文章
|
12天前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
138 73
|
7天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
40 21
|
14天前
|
人工智能 前端开发 Java
Spring AI Alibaba + 通义千问,开发AI应用如此简单!!!
本文介绍了如何使用Spring AI Alibaba开发一个简单的AI对话应用。通过引入`spring-ai-alibaba-starter`依赖和配置API密钥,结合Spring Boot项目,只需几行代码即可实现与AI模型的交互。具体步骤包括创建Spring Boot项目、编写Controller处理对话请求以及前端页面展示对话内容。此外,文章还介绍了如何通过添加对话记忆功能,使AI能够理解上下文并进行连贯对话。最后,总结了Spring AI为Java开发者带来的便利,简化了AI应用的开发流程。
224 0
|
12天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
12天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
21天前
|
XML JSON Java
Spring Boot 开发中常见的错误
本文总结了 Java 开发中常见的几个问题及其改进方法,包括:1. 过度使用 `@Component` 注解;2. `@ResponseBody` 注解的错误用法;3. `@Autowired` 的不当使用;4. `application.properties` 管理不善;5. 异常处理不当。每部分详细解释了错误情况和建议的改进方案,并提供了相应的代码示例。
47 11
|
21天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
38 5
|
19天前
|
前端开发 Java 开发者
这款免费 IDEA 插件让你开发 Spring 程序更简单
Feign-Helper 是一款支持 Spring 框架的 IDEA 免费插件,提供 URL 快速搜索、Spring Web Controller 路径一键复制及 Feign 与 Controller 接口互相导航等功能,极大提升了开发效率。
|
2月前
|
前端开发 JavaScript Java
如何使用 Spring Boot 和 Angular 开发全栈应用程序:全面指南
如何使用 Spring Boot 和 Angular 开发全栈应用程序:全面指南
51 1
|
26天前
|
XML Java 数据格式
Spring Boot 开发中的常见失误
本文深入分析了Spring Boot开发中常见的失误,包括不当使用@Component、@ResponseBody、@Autowired注解,以及不良的异常处理和日志记录实践,提供了有效的规避策略,帮助开发者提升代码质量和系统性能。

热门文章

最新文章