通常模式
Spring 对 "@Bean"注解的要求是必须是可重写,所以"public","protected","package"这几种修饰都是可以的。
简单验证:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class Config {
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
import org.springframework.web.client.RestTemplate;
public class MyService {
RestTemplate restTemplate;
public MyService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String getHelloWorld() {
return restTemplate.getForObject("http://httpbin.org/ip", String.class);
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.web.client.RestTemplate;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new org.springframework.context.annotation.AnnotationConfigApplicationContext(Config.class);
MyService myService = new MyService(context.getBean(RestTemplate.class)) ;
System.out.println("Hello world from: "+myService.getHelloWorld() );
}
}
运行输出:
Hello world from: {
"origin": "114.251.201.2"
}
反过来说, "private" 是不可以的
https://wmlx-new-image.oss-cn-shanghai.aliyuncs.com/images/20241108/049f7618451a95687abc10de493cce41.png
另外, "static" 方法也是可以被 "@Bean" 修饰的。
摘一段源码文档:
«Typically, @Bean methods are declared within @Configuration classes. In this
case, bean methods may reference other @Bean methods in the same class by
calling them directly. This ensures that references between beans are
strongly typed and navigable. Such so-called 'inter-bean references' are
guaranteed to respect scoping and AOP semantics, just like getBean() lookups
would. These are the semantics known from the original 'Spring JavaConfig'
project which require CGLIB subclassing of each such configuration class at
runtime. As a consequence, @Configuration classes and their factory methods
must not be marked as final or private in this mode.»
最后一句机翻一下:
«这些是原始“Spring JavaConfig”项目中已知的语义,需要在运行时对每个此类配置类进行 CGLIB
子类化。因此,在此模式下,不得将@Configuration类及其工厂方法标记为最终或私有。»
所以通常模式 "final" 和 "private" 修饰是不可以的。
小模式(Lite Mode)
"@Bean" 直接定义的 "@Component" \ "@Service" 里:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class MyService {
@Autowired
RestTemplate restTemplate;
public String getHelloWorld() {
return restTemplate.getForObject("http://httpbin.org/ip", String.class);
}
@Bean
private RestTemplate restTemplate() {
return new RestTemplate();
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyService.class);
MyService myService = context.getBean(MyService.class);
System.out.println("Hello world from: "+myService.getHelloWorld() );
}
}
这种情况下,定义成 "private" 是可以。
总结
小模式下可以为"private", 通常模式下不可以为"private", 限制更少的 "package" 都是可以的