Java Annotation

对于注解而言,若没有相应处理器,那它和注释没什么区别。

Java注解示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 声明注解使用的地方。 这里是方法级。
@Target(ElementType.METHOD)

//声明注解的生命时长。 这里是在运行时被虚拟机获得,所以可以使用反射来读。
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase{
int id();
String description() default "no description";
}

class A{
@UseCase(id=1,description="......")
void methodA{...}

....
}

class UseCaseTracker{
public static void trackUseCases(List<Integer> useCases, Class<?> cl){
for(Method m: cl.getDeclaredMethods()){
UseCase uc=m.getAnnonation(UseCase.class);
if(uc!=null){
print(uc.id(), uc.description());
}
}
}
}

另外,注解特别适用于生成框架的“样板文件”(boilerplate)代码。如Hibernate、Spring Boot等。

Spring

IoC 的一种类型是依赖注入。

ApplicationContext接口代表了Spring IoC容器,它负责实例化、配置并装配beans。

而容器是通过读配置metadata来获取配置的指令,其中,metadata包括XML、Java 注解或Java 代码。

@Configuration 表明该类可声明@Bean方法,并可Spring容器处理而产生Bean定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class HelloWorldConfiguration {

//等价于<bean id="provider", class="..."/>
@Bean
public MessageProvider provider() {
return new HelloWorldMassgeProvider();
}

@Bean
public MessageRenderer renderer() {
MessageRenderer renderer = new StandardOutMessageRenderer();
renderer.setMessageProvider(provider());
return renderer;
}
}

相应的测试代码

1
2
3
4
5
6
7
8
public class HelloWorldSpringAnnotated {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext
(HelloWorldConfiguration.class);
MessageRenderer renderer = ctx.getBean("renderer", MessageRenderer.class);
renderer.render();
}
}

以上代码也可以将Bean定义到外面,然后通过@ComponentScan来引入,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package ch3.annotated

@Service("provider")
class ConfigurableMessageProvider implements MessageProvider {
private String message;
//基于构造器的注入
@Autowired
public ConfigurableMessageProvider(
@Value("Cofigurable message") String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}

//-------
@Service("renderer")
class StandardOutMessageRenderer implements MessageRenderer {
private MessageProvider messageProvider;

public void render() {
System.out.println(messageProvider.getMessage());
}

//基于Setter注入
@Autowired
public void setMessageProvider(MessageProvider provider) {
messageProvider = provider;
}

public MessageProvider getMessageProvider() {
return messageProvider;
}
}

//--------
//启动 @Component的扫描
@ComponentScan("ch3.annotated")
@Configuration
public class HelloWorldSpringAnnotated {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext
(HelloWorldSpringAnnotated.class);
MessageRenderer renderer = ctx.getBean("renderer", MessageRenderer.class);
renderer.render();
}
}

由以上,可以引出Spring Boot中的 @SpringBootApplication。

它等价于 @ComponentScan、@Configuration、@EnableAutoConfiguration。