简体   繁体   中英

How to create simple Factory design pattern in Spring-boot?

Having this StorageFactory.java class which needs to be called from a Singleton:

@Component
@Configuration
@PropertySource("classpath:application.properties")
public class StorageFactory {

    @Value("${storage.type}")
    private static String storageTypeString;

    @Autowired
    private IApplicationProperties applicationProperties;

    @Autowired
    private Environment env;

    private static StorageType storageType;

    public static IEntityStorage create() {
        IEntityStorage storage = null;

        storageType = applicationProperties.getStorageType();

        switch (storageType){
            case File:
                storage = new FileStorageImpl();
                break;

            default:
                throw new IllegalArgumentException("storage.type in application.properties is invalid.");
        }

        return storage;
    }

    public static StorageType getStorageType() {
        return storageType;
    }
}

The call from the Singleton:

public final class DataManager {

    private static StorageType storageType;

    private static IEntityStorage storage;

    private static DataManager instance = null;

    protected DataManager() {
        storage = StorageFactory.create(); <<<< Calling from here to create the factory
        storage.init();
        loadAll();
        storageType = StorageFactory.getStorageType();
    }

    public static DataManager getInstance() {
        if (instance == null){
            synchronized (DataManager.class){
                if (instance == null){
                    instance = new DataManager();
                }
            }
        }
        return instance;
    }
}

What i'm trying to do is the use the Autowired ApplicationProperites.java (inside StorageFactory .java) to get my property (storageType).

I tried to solve the Autowiring issue with several approached and it didn't work.

What can I do in order to get the value from the property file in this stage?

You can use @Autowired with @Qualifier annotations. Let us take an example, there is one interface but there are multiple implementations. You want to different implementation in different place. To understand more on this, refer this link. https://www.mkyong.com/spring/spring-autowiring-qualifier-example/ .

I provide a very basic one for your understanding.

@Component(value="bmw") 
public BMW implements Vehicle {}

@Component(value="mercedes") 
public Mercedes implements Vehicle {}

public class MyActualClass {

@Autowired @Qualifier("bmw")
private Vehicle vehicle;
 ... other code goes here
}

DataManager is not managed by Spring and hence when you call StorageFactory.create() inside the constructor you should see a NullPointerException on applicationProperties.getStorageType()

Add @Component on the DataManager so that spring creates the singleton for you instead of you separately creating the DataManager singleton object and then also autowire the StorageFactory inside the DataManager

Try this.

@Component
public class StorageFactory {
    private static IApplicationProperties applicationProperties;

    @Autowired
    private StorageFactory(IApplicationProperties applicationProperties) {
        StorageFactory.applicationProperties = applicationProperties;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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