AppConfig.java返回bean与私有构造函数?

时间:2016-10-16 10:42:33

标签: java spring spring-ioc private-constructor

由于安全性而没有注释扫描的AppConfig.java,并且由于更难绑定而没有通过app-config.xml进行配置,我创建了像这样的spring-beans实例:

@Configuration
public class AppConfig {
  @Bean
  public AddressService addressService(){
    return new AddressService();
  }
}

一切都很好但是如果我想阻止其他人创建AddressService的实例呢?通常我会将构造函数声明为private,但编译器会给我一个错误,我无法再访问AddressServiceAppConfig的私有构造函数了!

为了完整性,这是AddressService

public final class AddressService {
  private AddressService(){}
}

2 个答案:

答案 0 :(得分:3)

这是一个有效的解决方案。

@Configuration
public class AppConfig {
    public static class AddressService {
        private AddressService() {}
    }
    @Bean
    public AddressService addressService() {
        return new AddressService();
    }
}

答案 1 :(得分:0)

创建一个公共接口和实现类包private。方法AddressingService是公共接口,AddressingServiceImpl只是包含私有@Service注释。现在没有人能够创建spring-bean的实例,并且根据您的bean范围,只有一个实例可供其他实例使用。您可以将bean自动装配为@Autowired AddressingService

示例junit测试用例,用于测试AddressingServiceImpl是否直接在同一个包中的任何类中使用。

在这种情况下,类位于src / main / java / com / address包中。并在src / test / java / com / address。

中创建测试类
package com.address;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Arrays;
import org.junit.Test;
import org.junit.*;

public class BeansInitTest {

@Test
public void test() {
    File[] files = new File("src/main/java/com/address").listFiles((File   dir, String name) -> {
        return name.endsWith(".java") &&    !name.equals(AddressServiceImpl.class.getSimpleName() + ".java");
    }
    );

    Arrays.asList(files)
            .stream().forEach(clazz -> checkInstanceCreation(clazz, AddressServiceImpl.class.getSimpleName()));
}

private void checkInstanceCreation(File clazz, String name) {
    try (BufferedReader reader = new BufferedReader(new FileReader(clazz))){

        reader.lines().forEach(l -> {
            Assert.assertFalse(l.contains(name));
        });

    }catch(Exception e){
        throw new RuntimeException(e);
    }
}

}

请注意,这只是一个示例,可以根据需要进行概括。