Spring in Action(一) Core Spring:Advanced Wiring

Spring的核心是dependency injection (DI) and aspect-oriented programming (AOP).

第一章概览一下什么是Spring,以及DI和AOP是怎么解耦(decoupling )应用组件的。

第二章讲模块、bean怎么连接起来,我们会了解spring提供的三种配置方式:自动配置,基于java的配置和用xml配置。【wiring beans,不清楚标准翻译法,暂翻译为连接,装配,反正大概就是这个意思】

第三章延续第二章讲一些高级的技术技巧,包括带有特定条件的配置,自动装配时的歧义处理,域,以及Spring表达式语言。【Spring Expression Language)】

第四章讲Spring的AOP如何解耦全路服务(比如安全控制及审计)decouple system-wide services (such as security and auditing)  】

 


3.1 环境与配置文件:数据库配置,加密算法,外部系统的集成等都是一些开发环境,一个可行的方案是利用比如说maven的profile,通过选用不同的类或xml文件进行rebuild来实现不同环境下的应用搭建,spring有比这个更好的方案。

3.1.1 java上配置@Profile来达到目的,3.2以上的spring可以把这个注解放到method上。相应的,xml在顶级或者子集的beans上增加profile属性来达到这个目的。

3.1.2 profile激活方式,两个级别:spring.profiles.active ,spring.profiles.default. 前者优先级高,后者优先级低,六种方式:初始化DispatcherServlet 的参数,web应用的上下文参数,JNDI键值对,环境变量,JVM系统属性,继承测试类的@ActiveProfiles
注解。自由配对组合。

 

3.2 条件bean

@Conditional注解,参数为一个实现了Condition接口的类.Condition的matches方法传入的参数有ConditionContext:

1 public interface ConditionContext {
2     BeanDefinitionRegistry getRegistry();
3     ConfigurableListableBeanFactory getBeanFactory();
4     Environment getEnvironment();
5     ResourceLoader getResourceLoader();
6     ClassLoader getClassLoader();
7 }

以及AnnotatedTypeMetadata :

public interface AnnotatedTypeMetadata {
    boolean isAnnotated(String var1);
    Map<String, Object> getAnnotationAttributes(String var1);
    Map<String, Object> getAnnotationAttributes(String var1, boolean var2);
    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);
    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
}

事实上,Profile就是通过这种方式实现的。

1 @Target({ElementType.TYPE, ElementType.METHOD})
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Conditional({ProfileCondition.class})
5 public @interface Profile {
6     String[] value();
7 }
 1 class ProfileCondition implements Condition {
 2     ProfileCondition() {
 3     }
 4 
 5     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
 6         if(context.getEnvironment() != null) {
 7             MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
 8             if(attrs != null) {
 9                 Iterator var4 = ((List)attrs.get("value")).iterator();
10 
11                 Object value;
12                 do {
13                     if(!var4.hasNext()) {
14                         return false;
15                     }
16 
17                     value = var4.next();
18                 } while(!context.getEnvironment().acceptsProfiles((String[])((String[])value)));
19 
20                 return true;
21             }
22         }
23 
24         return true;
25     }
26 }

3.3 如果你足够敏锐的话,在之前的章节就应该有一个问题萦绕在你的脑海中,那就是如果同一个接口有多个实现类被放到bean声明中,或者多个@Component注解被ComponentScan发现,这中情况该如何处理?

3.3.1用@Primary可以指定一个默认选择。xml中则是primary=“true”

3.3.2 在@AutoWired或@Inject上用@Qualifier注解指定一个全限定名,bean的全限定名默认是id,id默认是首字母小写的类名。当然,全限定名和id都是可以指定的。另一种方式是创建自定义的限定注解,全部注解一致时匹配。

 

3.4 bean的域

按前面说的,正常情况下bean只会复用同一个引用,也就是说,相当于每个bean都是单例模式。除了这种模式外还有其他模式可供选择,Prototype 每次都创建一个新的bean,用了就扔,Session 在web应用中没创建一个session就会new一个,Request 在web应用中对于一个Request,new一个bean。

java注解:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) ;xml属性:scope=“prototype”

3.4.1 request和session域.TODO:web看完后我再回头修改。

 

posted @ 2017-06-16 16:58  剑侠飞蓬  阅读(296)  评论(0编辑  收藏  举报