深入理解spring注解之@Bean注解

@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};

@AliasFor("value")
String[] name() default {};

Autowire autowire() default Autowire.NO;

String initMethod() default "";

String destroyMethod() default "(inferred)";
}

value -- bean别名和name是相互依赖关联的,value,name如果都使用的话值必须要一致
name -- bean名称,如果不写会默认为注解的方法名称
autowire -- 自定装配默认是不开启的,建议尽量不要开启,因为自动装配不能装配基本数据类型、字符串、数组等,这是自动装配设计的局限性,以及自动装配不如显示依赖注入精确
initMethod -- bean的初始化之前的执行方法,该参数一般不怎么用,因为可以完全可以在代码中实现
destroyMethod -- bean销毁执行的方法
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

package net.ydstudio.practise.bean;

import org.springframework.context.annotation.*;

/**
* 功能描述:<br/>
* @Bean意思是定义一个bean,该注解是一个方法级别上的注解,可以使用在@Configuration的类里,也可以
* 在@Component注解的类里,添加的bean的id为方法的名称
*
* @Date 2019/4/23 19:36
*/
@Configuration
public class AppConfig {

/**
*
* 下面的代码就相当于在xml之中添加下面的配置
* <beans>
* <bean id="transferService" class="net.ydstudio.practise.bean.TransferServiceImpl“ ></bean>
* </beans>
*
* 还能够使用@Scope注解来指定使用@Bean定义的bean
* singleton : 单例,整个应用中只存在一个实例bean
* prototype : 与单例相对,每次getBean都会重新生成一个Bean。
* request : web环境下,每个请求都会创建一个bean,在一次请求中只存在一个Bean,不同request的bean不同
* session : web环境下,session生命周期下,获取的是同一个bean
*
* 默认情况下,所有单实例bean都会在创建spring容器的时候创建,
* 如果在bean第一次使用的时候创建,我们称为懒加载
* 配置很简单,在创建bean的方法上添加@Lazy注解即可
*
* @return net.ydstudio.practise.bean.TransferService
* @date 2019/4/23 19:41
*/
@Bean
@Lazy
@Scope("singleton")
public TransferService transferService(){
return new TransferServiceImpl();
}

/**
* @Bean可以依赖其他任意数量的bean,如果TransferService依赖Foo,我们可以通过方法参数实现这个依赖
*
* @param: foo
* @return net.ydstudio.practise.bean.TransferService
* @date 2019/4/24 11:23
*/
@Bean
public TransferService transferService(Foo foo){
return new TransferServiceImpl(foo);
}

/**
*
* 任何使用@Bean定义的bean,也可以执行生命周期的回调函数
* 类似@PostConstruct and @PreDestroy的方法
*
* @return net.ydstudio.practise.bean.Foo
* @date 2019/4/23 19:49
*/
@Bean(initMethod = "init")
public Foo foo(){
return new Foo();
}

/**
* 任何使用@Bean定义的bean,也可以执行生命周期的回调函数
* 类似@PostConstruct and @PreDestroy的方法
* @param:
* @return net.ydstudio.practise.bean.Bar
* @date 2019/4/23 19:50
*/
@Bean(destroyMethod = "cleanUp")
public Bar bar(){
return new Bar();
}

/**
*
* 默认情况下bean的名称和方法名称相同,你也可以使用
* 注解中的name属性进行指定
*
* @param:
* @return net.ydstudio.practise.bean.Foo
* @date 2019/4/23 19:52
*/
@Bean(name = "myFoo")
public Foo getFoo(){
return new Foo();
}

/**
* 可以通过某些条件,来选择是否注册Bean,通过@Condition注解来实现
* 实现Condition接口,并重写matches方法,根据该方法返回的布尔值来决定是否注册Bean
* @return net.ydstudio.practise.bean.Book
* @date 2019/4/24 11:54
*/
@Bean
@Conditional(MyCondition.class)
public Book book(){
return new Book();
}
}
public class Bar {

public void cleanUp(){
System.out.println("---111111cleanUp---");
}

@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Bar{");
sb.append('}');
return sb.toString();
}
}

public class Book {
private String name;
private BigDecimal price;
private Date publishDate;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public BigDecimal getPrice() {
return price;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

public Date getPublishDate() {
return publishDate;
}

public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
}
public class Foo {
public void init(){
System.out.println("初始化之前---init---初始化之前");
}

@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Foo{");
sb.append('}');
return sb.toString();
}
}
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

/**
* 根据环境变量是否存在my.env=hello的属性来决定是否创建,
* 可以通过启动参数指定-Dmy.env=hello来测试。
**/
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("my.env");
if ("hello".equals(property)) {
return true;
}
return false;
}
}

public interface TransferService {
}
public class TransferServiceImpl implements TransferService{

private Foo foo;

public TransferServiceImpl(Foo foo) {
this.foo = foo;
}

public TransferServiceImpl() {
}
}
  • 作者: Sam
  • 发布时间: 2019-04-23 23:36:01
  • 最后更新: 2019-12-09 23:03:26
  • 文章链接: https://ydstudios.gitee.io/post/2d1810c4.html
  • 版权声明: 本网所有文章除特别声明外, 禁止未经授权转载,违者依法追究相关法律责任!