@Bean不加public修饰会生效吗?为什么?

@Bean不加public修饰会生效吗?为什么

@Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

证明生效或者没生效

阅读 1.5k
1 个回答

通常模式

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 是不可以的

另外, 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类及其工厂方法标记为最终或私有。

所以通常模式 finalprivate 修饰是不可以的。

小模式(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 都是可以的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题