ROO中的@Configuration

问题提出

当我们在ROO中为Entity添加了@RooJavaBean注解时,ROO会为我们自动生成了一个Region_Roo_Configurable.aj文件,其中代码如下:

privileged aspect Region_Roo_Configurable {

    declare @type: Region: @Configurable;

}

如何理解这段代码?下面一步步进行解析。

declare @type:

google了这篇文章

AspectJ 5 supports a new kind of declare statement, declare annotation. This takes different forms according to the recipient of the annotation: declare @type for types, declare @method for methods, declare @constructor for constructors, and declare @field for fields.

可以看到,除了@type之外还有许多形如@**的标签。一般形式如下所示:

declare @<kind> : ElementPattern : Annotation ;

要理解这个注解的作用,首先要了解AOP中静态横切动态横切的概念。这里有一段通俗的解释:

动态横切是通过切入点(pointcut)和链接点(joint point)在一个方面(aspect)中的创建行为的过程;方面(aspect)定义了所有的链接点,切入点以及通知(advice),以便把需要切入的职责(interweave)注入到原来的对象中;

静态横切是通过在不修改原有职责的基础上增加新的职责;以往我们用过类的继承来实现,但继承是种强依赖关系,怎么让他们松藕,这个时候我们用静态横切,用mixin;

declare @<kind>注解实现了静态横切的声明功能,例如:

//为data package下的所有类添加Cacheable接口
declare parents : data.* implements Cacheable

//为banking直接和间接子包下的类加上@PrivacyControlled注解
declare @type:  banking..* :  @PrivacyControlled;

由此可以看出declare @type: Region: @Configurable;的意思是给所有的Region添加了@Configurable注解。

@Configurable

google了这篇文章,里面提到:

Since spring 2, you were writing your bean configurations to xml files. But, Spring 3 gave the freedom to move bean definitions out of xml files. Now, you can give bean definitions in your java files itself. This is called JavaConfig feature (using @Configuration annotation).

也就是说,我们可以用过@Configuration来配置bean,而不是通过xml配置文件。

假设我们有如下接口声明:

public interface DemoManager {
    public String getServiceName();
}

实现如下:

public class DemoManagerImpl implements DemoManager 
{
    @Override
    public String getServiceName()
    {
        return "My first service with Spring 3";
    }
}

那么我们不用xml对其进行配置,用@Configuration,如下所示:

@Configuration
public class ApplicationConfiguration {

    @Bean(name="demoService")
    public DemoManager helloWorld() {
        return new DemoManagerImpl();
    }
}

可见,@Configuration注解声明了ApplicationConfiguration为一个配置类,@Bean(name="demoService")可以看成是xml配置中的<bean class="**.**.ApplicationConfiguration " id="demoService"/>
</beans>
。于是,我们可以这样取出bean:

ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
DemoManager  obj = (DemoManager) context.getBean("demoService");
System.out.println( obj.getServiceName());

另外,@Configuration注解从属于Annotation Type Configuration这个主题下,这里有详细的介绍。

例如,可以通过

<beans>
    <context:annotation-config/>
    <bean class="com.acme.AppConfig"/>
</beans>

或者

<context:component-scan/>

令Configuration生效。还可以通过@Inject Environment env;

 @Configuration
 public class AppConfig {
     @Inject Environment env;

     @Bean
     public MyBean myBean() {
         MyBean myBean = new MyBean();
         myBean.setName(env.getProperty("bean.name"));
         return myBean;
     }
 }

令Configuration拥有访问其他bean的能力。也可以用@Value注解做到这一点:

 @Configuration
 @PropertySource("classpath:/com/acme/app.properties")
 public class AppConfig {
     @Value("${bean.name}") String beanName;

     @Bean
     public MyBean myBean() {
         return new MyBean(beanName);
     }
 }

更详细的用法参考上面给出的文档

总结

综上,可以这样理解ROO的行为:@RooJavaBean注解让ROO用declare @type: Region: @Configurable;语句为我们的实体类添加了Configurable特性,使我们可以直接在entity.java里面配置bean,而不用去写xml配置。

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据