2016-10-16 5 views
3

wegen der Sicherheit ein AppConfig.java ohne Annotation-Scannen und mit und ohne Konfiguration über eine app-config.xml wegen schwerer Bindung, ich schaffe Instanzen feder Bohnen wie folgt aus:AppConfig.java Bean mit privatem Konstruktor zurückgeben?

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

Alles funktioniert gut, aber was ist, wenn Ich mag um zu verhindern, dass andere eine Instanz von AddressService erstellen? Normalerweise würde ich den Konstruktor als privat deklarieren, aber der Compiler gibt mir einen Fehler, dass ich nicht mehr auf den privaten Konstruktor von AddressService im AppConfig zugreifen kann!

Der Vollständigkeit halber ist dies die AddressService:

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

Antwort

0

Erstellen Sie eine öffentliche Schnittstelle und die Implementierungsklasse Paket privat. Mittel AddressingService ist öffentliche Schnittstelle und AddressingServiceImpl ist nur Paket privat mit @Service Annotation. Jetzt kann niemand mehr eine Instanz Ihrer Spring-Bean erstellen, und nur eine Instanz wird basierend auf Ihrem Bean-Umfang für andere verfügbar sein. Sie können die Bean als @Autowired AddressingService autowire.

Ein Beispiel für einen Junit-Test, um zu testen, ob der AddressingServiceImpl direkt in einer Klasse innerhalb desselben Pakets verwendet wird.

In diesem Fall befinden sich die Klassen im Paket src/main/java/com/address. und die Testklasse wird in src/test/java/com/address erstellt.

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); 
    } 
} 

}

Bitte beachten Sie, dass dies nur ein Beispiel und kann je nach Bedarf verallgemeinert werden.

+0

Warum die Schnittstelle? Warum deklarieren Sie das Konstruktorpaket nicht - privat? –

+0

Eigentlich, was ändert es? Das OP kann den Annotation-Scan nicht verwenden. Also muss er noch "new AddressingService" machen können, was bedeutet, dass der Konstruktor auch für andere sichtbar ist? – alexbt

+0

@Alex Der Konstruktor wäre im selben Paket sichtbar, er sagte 'package-private' was ist' default' oder 'protected'. –

2

Dies ist eine funktionierende Lösung.

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