深入Spring源码专题(9)

133 阅读1分钟

这是我参与2022首次更文挑战的第15天,活动详情查看2022首次更文挑战

@Component("provider")
public class SpringBeanMessageProvider implements MessageProvider{
    @Override
    public String getMessage(){
        return "Spring Bean";
    }
}

@Service("renderer")
public class StandardOutMessageRenderer implements MessageRenderer{
    private MessageProvider messageProvider;
        @Override
    public void render(){
        if(messageProvider == null){
            throw new RuntimeException(StandarOutMessageRenderer.class.getName);
        }
        System.out.println(messageProvider.getMessage());
    }
    @Override
    public void setMessageProvider(MessageProvider messageProvider){
        this.messageProvider=messageProvider;
    }
    @Override
    public MessageProvider getMessageProvider(){
        return this.messageProvider;
    }
}

当使用XML(在app-context-annotation.xml文件中)配置来启动Spring的ApplicationContext时,Spring将查找这些组件并使用指定名称实例化Bean。

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmls="http://www.springframework.org/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.ozx.annotation" />
</beans>

使用这两种方法不会从ApplicationContext获取Bean的方式。

public class DeclareSpringComponents{
    public static void main(String... args){
        GenericXmlApplicationContext ctx=new GenericXmlApplicationContext();
        ctx.load("classpath:spring/app-context-xml.xml");
        ctx.refresh();
        MessageRenderer messageRenderer = ctx.getBean("renderer",MessageRenderer.class);
        messageRenderer.render();
        ctx.close();
    }
}

GenericXmlApplicationContext而不是DefaultListableBeanFactory的一个实例被实例化。GenericXmlApplicationContext类实现了ApplicationContext接口,并能够通过XML文件中定义的配置启动Spring的ApplicationContext。

使用Java配置

将app-context-xml.xml替换为配置类,而无须修改标识正在创建的bean类型的类。当应用程序所需要的bean类型是不能修改的第三方库时,采用这种做法。配置类使用@Configuration注解,并包含用@Bean注解的方法。这些方法由SpringIoC容器直接调用来实例化Bean,Bean名称与用于创建它的方法的名称相同。

一个配置类如下所示:

public class BeanConfiguration{
    @Bean
    public MessageProvider provider(){
        return new MessageProvider();
    }
    
    @Bean
    public MessageRenderer renderer(){
        MessageRenderer renderer = new StandardOutMessageRenderer();
        renderer.setMessageProvider(provider());
        return renderer;
    }
}

要从这类中读取配置信息,还需要一个不同的ApplicationContext实现。

public class BeanSpringAnnotated{
	public static void main(String... args){
	ApplicationContext ctx = new AnnotationConfigApplicaitonContext(BeanConfiguration.class);
	MessageRenderer messageRenderer = ctx.getBean("renderer",MessageRenderer.class);
	messageRenderer.render();
	}
}

实例化的是AnnotationConfigApplicationContext而不是DefaultListableBeanFactory的一个实例,AnnotationConfigApplicationContext类实现了ApplicationContext接口,并且能够根据BeanConfiguration类定义的配置信息启动Spring的ApplicationContext。