一.spring-core IoC container(3) 基于javaCode的配置方式

来源:互联网 发布:k均值聚类算法 matlab 编辑:程序博客网 时间:2024/05/19 13:19

前面两节学习了IoC容器的XML配置和annotation的配置方式,本节学习 一下IoC container 基于java-code的配置。

@Bean and @Configuration 概述

spring基于javaCode的配置方式的核心是类级别的注解@Configuration 和 方法级别的注解@Bean
@Bean注解用来表明此方法实例化,配置,初始化了一个新对象,并且交给container管理。有点类似于XML中的<bean/> 配置,一般用于被@Configuration 注解的类中,也可以用于被@Component 注解的类中。
@Configuration表明这个类是Bean 定义的“源”

@Configurationpublic class AppConfig {    @Bean    public MyService myService() {        return new MyServiceImpl();    }}换成XML是:<beans>    <bean id="myService"   class="com.acme.services.MyServiceImpl"/></beans>

AnnotationConfigApplicationContext

使用javaCode配置的方式没有了XML的配置文件,那么该如何初始化容器呢?
在spring3.0以后引入了一个新类AnnotationConfigApplicationContext 它能接受被@Configuration 标注的类作为注入源,也能接受 @Component 标注的类作为注入源。
@Configuration 标注的类作为注入源时,此类本身也会作为一个bean定义被注册,同时,所有的被@Bean 标注的方法也会作为bean定义被注入
@Component 标注的类作为注入源时, JSR-330 的注解都会被作为bean被注入,为解决依赖的@Autowired@Inject 也会作为bean被注入

与XML配置时容器初始化的方式类似,javaCode初始化的方式如下:

//通过构造public static void main(String[] args) {    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);    MyService myService = ctx.getBean(MyService.class);    myService.doStuff();}//也可以后续调用register手动注册public static void main(String[] args) {    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();    ctx.register(AppConfig.class, OtherConfig.class);    ctx.register(AdditionalConfig.class);    ctx.refresh();    MyService myService = ctx.getBean(MyService.class);    myService.doStuff();}//使用scanpublic static void main(String[] args) {    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();    ctx.scan("com.acme");    ctx.refresh();    MyService myService = ctx.getBean(MyService.class);}

对于Web工程,使用的AnnotationConfigWebApplicationContext 在此不多做说明

@Bean 使用

声明一个Bean

@Configurationpublic class AppConfig {    @Bean    public TransferService transferService() {        return new TransferServiceImpl();    }}//xml写法<beans>    <bean id="transferService" class="com.acme.TransferServiceImpl"/></beans>

使用上述方法会在ApplicationContext 注册一个bean的定义,bean默认的名字即为方法名。

Bean的依赖
如果Bean中有以来,可以通过在方法中加入参数进行注入

@Configurationpublic class AppConfig {    @Bean    public TransferService transferService(AccountRepository accountRepository) {        return new TransferServiceImpl(accountRepository);    }}

bean初始化和销毁前动作
使用@Bean 一样可以执行Bean的生命周期方法

public class Foo {    public void init() {        // initialization logic    }}public class Bar {    public void cleanup() {        // destruction logic    }}@Configurationpublic class AppConfig {    @Bean(initMethod = "init")    public Foo foo() {        return new Foo();    }    @Bean(destroyMethod = "cleanup")    public Bar bar() {        return new Bar();    }}

使用 @Scope 确定Bean作用域

@Configurationpublic class MyConfiguration {    @Bean    @Scope("prototype")    public Encryptor encryptor() {        // ...    }}

自定义Bean的使用name

@Configurationpublic class AppConfig {    @Bean(name = "myFoo")    public Foo foo() {        return new Foo();    }}

@Configuration 的使用

注入Bean依赖

@Configurationpublic class AppConfig {    @Bean    public Foo foo() {        //注入Bar对象        return new Foo(bar());    }    @Bean    public Bar bar() {        return new Bar();    }}

@Import
下面的例子中,容器初始化过程中只需要加入ConfigB.class即可

@Configurationpublic class ConfigA {     @Bean    public A a() {        return new A();    }}@Configuration@Import(ConfigA.class)//@Import({ServiceConfig.class, RepositoryConfig.class})public class ConfigB {    @Bean    public B b() {        return new B();    }}

上一节介绍的@Autowired 也可以用在@Configuration 注解的类中实现自动装配的效果(当然对应的类需要在容器中注册)。

Java和XML 配置结合

有一些java的类在加载过程中需要给一系列的初始化值,比如DataSource 看下面一个例子:

@Configurationpublic class AppConfig {    @Autowired    private DataSource dataSource;    @Bean    public AccountRepository accountRepository() {        return new JdbcAccountRepository(dataSource);    }    @Bean    public TransferService transferService() {        return new TransferService(accountRepository());    }} system-test-config.xml:<beans>    <!-- enable processing of annotations such as @Autowired and @Configuration -->    <!--也可以使用 <context:component-scan base-package="com.acme"/>-->    <context:annotation-config/>    <!--在xml中引入properties文件-->    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>    <bean class="com.acme.AppConfig"/>    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">        <!--取得jdbc.properties文件中的值-->        <property name="url" value="${jdbc.url}"/>        <property name="username" value="${jdbc.username}"/>        <property name="password" value="${jdbc.password}"/>    </bean></beans>jdbc.properties文件:jdbc.url=jdbc:hsqldb:hsql://localhost/xdbjdbc.username=sajdbc.password=

使用:

public static void main(String[] args) {    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");    TransferService transferService = ctx.getBean(TransferService.class);    // ...}

上述例子中AppConfig 类是在xml中注册的,也可以不在此定义而使用@ImportResource 结合 @Value

@Configuration@ImportResource("classpath:/com/acme/properties-config.xml")public class AppConfig {    @Value("${jdbc.url}")    private String url;    @Value("${jdbc.username}")    private String username;    @Value("${jdbc.password}")    private String password;    @Bean    public DataSource dataSource() {        return new DriverManagerDataSource(url, username, password);    }}XML只需要引入propertiesproperties-config.xml<beans>    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/></beans>jdbc.properties文件:jdbc.url=jdbc:hsqldb:hsql://localhost/xdbjdbc.username=sajdbc.password=

使用:

public static void main(String[] args) {    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);    TransferService transferService = ctx.getBean(TransferService.class);    // ...}

获取配置信息

环境Environment 是容器的抽象集合,应用中的环境包括2个方面:配置和属性
配置:注册在容器中的bean的逻辑分组,只有初始化后才会生效,不管是通过XML的方式还是注解的方式,Bean都会成为”配置”,关联配置项的环境对象决定哪个配置文件生效,哪个配置文件默认生效
属性:属性文件在很多应用中扮演了重要角色,关联属性项的环境对象给用户提供了很方便的访问他们的接口
@Profile注解-配置
通过设定EnviromentActiveProfiles 可以决定当前context需要使用的配置环境,在开发中使用@Profile注解类或方法达到在不同情况下选择实例化不同的Bean
通过设定jvm的spring.profiles.active参数来设置环境
Web项目设置servlet的context.paramte

@Profile 可以用在类上,方法上,同时他是一个元注解-可以永远新建别的注解//用在类上:@Configuration@Profile("dev")public class StandaloneDataConfig {    @Bean    public DataSource dataSource() {        return new EmbeddedDatabaseBuilder()            .setType(EmbeddedDatabaseType.HSQL)            .addScript("classpath:com/bank/config/sql/schema.sql")            .addScript("classpath:com/bank/config/sql/test-data.sql")            .build();    }}//用在方法上@Configurationpublic class AppConfig {    @Bean    @Profile("dev")    public DataSource devDataSource() {        return new EmbeddedDatabaseBuilder()            .setType(EmbeddedDatabaseType.HSQL)            .addScript("classpath:com/bank/config/sql/schema.sql")            .addScript("classpath:com/bank/config/sql/test-data.sql")            .build();    }    @Bean    @Profile("production")    public DataSource productionDataSource() throws Exception {        Context ctx = new InitialContext();        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");    }}

激活某一套环境:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();ctx.getEnvironment().setActiveProfiles("dev");ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);ctx.refresh();

设置profile的默认使用环境:
@Profile()设置"default"即可

@Configuration@Profile("default")public class DefaultDataConfig {    @Bean    public DataSource dataSource() {        return new EmbeddedDatabaseBuilder()            .setType(EmbeddedDatabaseType.HSQL)            .addScript("classpath:com/bank/config/sql/schema.sql")            .build();    }}如果没有手动设置active的profile,那么上述的dataSource将会生效可以使用Environmentset对象的DefaultProfiles()设置

@PropertySource
使用@PropertySource 注解可以很方便的向spring的Environment 添加属性信息

@Configuration@PropertySource("classpath:/com/myco/app.properties")public class AppConfig {    @Autowired    Environment env;    @Bean    public TestBean testBean() {        TestBean testBean = new TestBean();        testBean.setName(env.getProperty("testbean.name"));        return testBean;    }}
0 0
原创粉丝点击