基于Java的容器配置

加粗样式@TOC

@Bean和@Configuration

Spring的基于java的配置的核心是@Configuration注解的类和@Bean注解的方法。
@Bean注解用来指明一个方法实例化、配置和初始化Spring IoC容器管理的一个新对象。@Bean的作用和配置文件中的<beans/>。
用@Configuration注解的类表明它是用作bean定义的源。另外,@Configuration注解类允许内部的bean依赖被定义,仅仅通过调用相同类中的其他@Bean方法。最简单的@Configuration的像下面这样:

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

AnnotationConfigApplicationContext

使用AnnotationConfigApplicationContext初始化Spring容器

ApplicationContext实现不仅能接收@Configuration类作为输入,而且@Component注解类和JSR-330 metadata注解的类。当@Configuration类作为输入时,@Configuration注解的类本身被作为一个bean定义,在其中@Bean注解的方法也作为bean定义。
和使用ClassPathXmlApplicationContext通过配置文件创建bean一样,可以使用AnnotationConfigApplicationContext通过@Configuration类作为bean的输入。这允许spring容器完全摆脱xml配置文件。

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

AnnotationConfigApplicationContext 不仅限于@Configuration注解的类。任何@Component和JSR-330注解的类可以作为构造器的输入。例如:

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(Class<?>…)构建容器

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

启用扫描组件

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}

AnnotationConfigWebApplicationContext支持web应用程序

AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext用于支持web的变体。当配置Spring ContextLoaderListener监听器、Spring MVC DispatcherServlet时使用这个实现。

<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited
            and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.acme.web.MvcConfig</param-value>
        </init-param>
    </servlet>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

Using the @Bean annotation

声明bean

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}

等同于之前的

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

接收生命周期回调

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

}

等同于

@Configuration
public class AppConfig {
    @Bean
    public Foo foo() {
        Foo foo = new Foo();
        foo.init();
    return foo;
    }

    // ...

}

指定作用域

@Configuration
public class MyConfiguration {

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

}

Using the @Configuration annotation

注入bean间的依赖

@Configuration
public class AppConfig {

    @Bean
    public Foo foo() {
        return new Foo(bar());
    }

    @Bean
    public Bar bar() {
        return new Bar();
    }

}

组合基于java的配置

使用@Import注解

像在xml配置文件中使用 <import/>来模块化配置,@Import注解允许从其它的配置类中加载@Bean定义。

@Configuration
public class ConfigA {

     @Bean
    public A a() {
        return new A();
    }

}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

    @Bean
    public B b() {
        return new B();
    }

}
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

    // now both beans A and B will be available...
    A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);
}

导入的@Bean的依赖间注入

@Configuration
public class ServiceConfig {

    @Autowired
    private AccountRepository accountRepository;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(accountRepository);
    }

}

@Configuration
public class RepositoryConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataSource);
    }

}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }

}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

有条件地包含@Configuration classes or @Beans

通常根据系统的某个状态有条件地启用或禁用一个完整的@Configuration类或者单个的@Bean方法是有用的。一个常用的例子是使用@Profile注解,在Spring环境中只有特定的模式启用是才激活beans。@Profile实际上是通过更灵活的@Conditional注解实现的。@Conditional注解实际上指的是org.springframework.context.annotation.Condition实现,在@Bean注册前会查询它。Condition接口提供了一个返回true或false的matches(…)方法 。@Profile使用的Condition实现:

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    if (context.getEnvironment() != null) {
        // Read the @Profile annotation attributes
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
        if (attrs != null) {
            for (Object value : attrs.get("value")) {
                if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
                    return true;
                }
            }
            return false;
        }
    }
    return true;
}

给容器中注册组件的方式

  1. 包扫描+组件标注注解(@Controller、@Service、@Repository、@Component)
  2. @Bean[导入第三方包里面的组件]
  3. @Import[快速给容器中导入一个组件]
    1). @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认为全类名;
    2). ImportSelector:返回需要导入的组件的全类名数组;
    3). ImportBeanDefinitionRegistrar:手动注册bean容器中
  4. 使用Spring提供给FactoryBean(工厂Bean)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值