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

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

@Bean and @Configuration 概述

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

@Configuration
public 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();
}
//使用scan
public 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

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

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

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

@Configuration
public 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
    }
}
@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public Foo foo() {
        return new Foo();
    }
    @Bean(destroyMethod = "cleanup")
    public Bar bar() {
        return new Bar();
    }
}

使用 @Scope 确定Bean作用域

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

}

自定义Bean的使用name

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

}

@Configuration 的使用

注入Bean依赖

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

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

@Configuration
public 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 看下面一个例子:

@Configuration
public 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/xdb
jdbc.username=sa
jdbc.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只需要引入properties
properties-config.xml
<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

jdbc.properties文件:
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.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();
    }
}
//用在方法上
@Configuration
public 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值