繁体   English   中英

Spring如何知道使用@Bean和方法调用进行注入的bean

[英]How Spring knows bean to inject with @Bean and method call

我正在尝试使用Spring Framework做一些事情,我想知道当使用Java配置时,Spring如何通过方法调用注入单例依赖?

范例:

@Configuration
public class AppConfiguration {

    @Bean
    public BlogRepository blogRepository() {
        return new BlogRepositoryImpl();
    }

    @Bean
    @Scope("prototype")
    public BlogService blogService() {
        return new BlogServiceImpl(blogRepository());
    }

    @Bean
    public AuthorService authorService() {
        return new AuthorServiceImpl(blogRepository());
    }
}

我知道该类也是一个bean,它由Spring代理,但是,由于我从该类内部调用blogRepository() ,因此代理不能处理该调用,因此Spring如何始终获取现有的BlogRepository单例?

当使用@Configuration注释类时,使用@Bean注释的方法由CGLIB代理包装。

如果它是对此方法的第一次调用,则将执行原始方法的主体并将结果对象存储在Spring上下文中。 所有后续调用仅返回从上下文中检索到的bean。

是什么让您认为代理无法处理呼叫?

Spring 可以生成类似于此子类的代理:

class AppConfigurationProxy extends AppConfiguration {
    private BlogRepository blogRepository;

    @Override
    public BlogRepository blogRepository() {
        if (blogRepository == null)
            blogRepository = super.blogRepository();
        return blogRepository;
    }

    // same for the other two @Bean methods
}

现在,无论AppConfiguration的方法调用它自己的blogRepository()方法多少次,它都将始终获得相同的对象。


更新:以上证明行之有效。

简单的Bean接口

public interface BlogRepository {
}

public interface BlogService {
}

public interface AuthorService {
}

简单的Bean类

它们没有任何实际逻辑,只是一个toString()实现可以显示对象的“身份”,类似于类Object的默认toString()实现。

public class BlogRepositoryImpl implements BlogRepository {
    @Override
    public String toString() {
        return "BlogRepositoryImpl@" + Integer.toHexString(hashCode());
    }
}

public class BlogServiceImpl implements BlogService {
    private BlogRepository blogRepository;
    public BlogServiceImpl(BlogRepository blogRepository) {
        this.blogRepository = blogRepository;
    }
    @Override
    public String toString() {
        return "BlogServiceImpl@" + Integer.toHexString(hashCode()) + "[blogRepository=" + this.blogRepository + "]";
    }
}

public class AuthorServiceImpl implements AuthorService {
    private BlogRepository blogRepository;
    public AuthorServiceImpl(BlogRepository blogRepository) {
        this.blogRepository = blogRepository;
    }
    @Override
    public String toString() {
        return "AuthorServiceImpl@" + Integer.toHexString(hashCode()) + "[blogRepository=" + this.blogRepository + "]";
    }
}

配置类

如问题中所定义。

public class AppConfiguration {
    public BlogRepository blogRepository() {
        return new BlogRepositoryImpl();
    }
    public BlogService blogService() {
        return new BlogServiceImpl(blogRepository());
    }
    public AuthorService authorService() {
        return new AuthorServiceImpl(blogRepository());
    }
}

像String这样的代理类可能已经实现了它

与答案顶部相同,仅使用所有方法即可完成。

public class AppConfigurationProxy extends AppConfiguration {
    private BlogRepository blogRepository;
    private BlogService blogService;
    private AuthorService authorService;
    @Override
    public BlogRepository blogRepository() {
        if (this.blogRepository == null)
            this.blogRepository = super.blogRepository();
        return this.blogRepository;
    }
    @Override
    public BlogService blogService() {
        if (this.blogService == null)
            this.blogService = super.blogService();
        return this.blogService;
    }
    @Override
    public AuthorService authorService() {
        if (this.authorService == null)
            this.authorService = super.authorService();
        return this.authorService;
    }
}

测试

public class Test {
    public static void main(String[] args) {
        // Show result without proxy
        AppConfiguration config = new AppConfiguration();
        System.out.println(config.blogRepository());
        System.out.println(config.blogService());
        System.out.println(config.authorService());

        // Show how only one BlogRepository is craeted when proxy is used
        config = new AppConfigurationProxy();
        System.out.println(config.blogRepository());
        System.out.println(config.blogService());
        System.out.println(config.authorService());
    }
}

输出量

BlogRepositoryImpl@1e81f4dc
BlogServiceImpl@7960847b[blogRepository=BlogRepositoryImpl@6a6824be]
AuthorServiceImpl@2c13da15[blogRepository=BlogRepositoryImpl@77556fd]

BlogRepositoryImpl@9e89d68
BlogServiceImpl@3b192d32[blogRepository=BlogRepositoryImpl@9e89d68]
AuthorServiceImpl@16f65612[blogRepository=BlogRepositoryImpl@9e89d68]

可以看出,第一部分没有使用代理,最后以BlogRepositoryImpl 3个不同实例BlogRepositoryImpl

通过使用代理的,只有一个实例BlogRepositoryImpl创建和共享即使blogService()调用blogRepository() “直接”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM