So i have
public class ApplicationConfig{
public static ApplicationConfig getCurrentInstance(){
//Something similar to this
if(instance==null){
FacesContext fc =FacesContext.getCurrentInstance();
if(fc==null)
return null;
wac = FacesContextUtils.getWebApplicationContext(fc);
}
instance =(ApplicationConfig)wac.getBean("appConfig");
}
return instance;
}
}
The way how the current Instance is retrieved differs from application1 and application2. Once I read it from spring, and once I use the plain singleton pattern.
Is there a way? both configs share some configurations - e.g.
public boolean isConfiguredForFoo() {
return getCurrentInstance().getPropertyFoo().equals("foo");
}
EDIT so finally I want to be bascially able to do the following, or something like it:
ApplicationConfig.getCurrentInstance().isApplication1();
Where ApplicationConfig is an abstract or interface, application1 with it's implementation of getCurrentInstance and application2 with it's own implementation.
Furthermore: calling isConfiguredForFoo() finally calls getCurrentInstance. I cannot pull this function up because there is no implementation of getCurrentInstance in the abstract class and defining static abstract method is illegal. What way is there to keep all the isXXXXConfigured() together in one place and sticking to the DRY principle?
i have dependencies to jsf and spring in applicationConfig for application1 and no dependencies in application2. How can I use most functions from ApplicationConfig from Application1, only avoiding the crucial getCurrentInstance() function which accesses these dependencies?
I don't understand what you want to archive?
But I suspect both applications retrieves the ApplicationConfig the same way.
App 1: Spring with a factory-method=getCurrentInstance
App 2: Manually calling getCurrentInstance();
I'm not sure what exactly you are doing, but the following might be useful:
public abstract class AppConfig {
private static AppConfig instance;
static {
if (whatever...)
instance = new AppConfig1();
else
instance = new AppConfig2();
}
public static AppConfig getInstance() {
return instance();
}
}
...
if (AppConfig.getInstance() instanceof AppConfig1)
...
If you are reusing some code for the configuration sometimes in Spring and sometimes outside, maybe you are better off rewriting different classes for both cases.
Related
I have an Interface and multiple implementation. I'm auto wiring the interface in classes for usage. I need to choose different implementation at runtime.
public class Util {
public void getClient();
}
Implementations
public class UtilOne implements Util {
public void getClient() {...}
}
public class UtilTwo implements Util {
public void getClient() {...}
}
#Configuration
public class AppConfig {
#Autowired
#Bean
#Primary
public Util utilOne() {
return new UtilOne();
}
#Autowired
#Bean
public Util utilTwo() {
return new UtilTwo();
}
}
#Component
public class DemoService {
#Autowired
private Util util;
}
For some reason if we are unable to get client in UtilOne, I want to switch to UtilTwo without restarting the app. I want to change the Util object in DemoService to UtilTwo object.
Property active.util will come from DB and can we updated from UI.
It doesn't work this way - if you have a certain implementation of Util wired to, say, class SampleClass (which is a singleton) you can't really change the implementation of the Util to something different without restarting the application context.
So instead of going this way, I suggest an alternative. You say that under certain conditions that evaluate in runtime you want to switch implementations. What kind of condition it is? Is it possible to extract this condition decision logic?
If so, you can autowire a special DynamicUtil that will hold the reference to all the utils and will call the required util depending on the condition:
// represents all possible business 'runtime' outcomes
enum ConditionOutcome {
A, B, C
}
interface ConditionEvaluator {
ConditionOutcome evaluate(); // when called in runtime will evaluate a condition that currently exists in the system
}
interface Util {
void foo();
ConditionOutcome relevantOfOutcome();
}
class Utill1Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.A;}
}
class Utill2Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.B;}
}
class Utill3Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.C;}
}
class DynamicUtil {
private final Map<ConditionOutcome, Util> possibleImpls;
private final ConditionEvaluator evaluator;
public class DynamicUtil(List<Util> allImplementations, ConditionEvaluator evaluator) {
// create a map by calling the 'relevantOfOutcome' per util impl in a loop
this.evaluator = evaluator;
}
public void foo() {
ConditionOutcome key = evaluator.evaluate();
// pick the relevant implementation based on evaluated key
possibleImpls.get(key).foo();
}
}
Now with such a design you can dynamically add new possible outcomes (along with utils that should implement them. You classes in the system will have to autowire DynamicUtil though, so effectively you'll introduce one additional level of indirection but will gain flexibility
class SampleClass { // a business class that will need to work with util capable of being changed during the runtime
#Autowired
private DynamicUtil util;
...
}
You can try approach with delegating proxy. Have a primary Util bean that is just wrapper around actual implementation and allow to change its internal delegate at runtime. In addition you can create something like manager/helper class that holds references to all actual implementation beans to simplify switching between them.
#Component
#Primary
public class DelegatingUtil implements Util {
private Util delegate;
public void setDelegate(Util delegate){ this.delegate = delegate; }
public Util getDelegate(){ return delegate; }
public void getClient() {
return delegate.getClient();
}
}
And where switching logic applies:
// Use #Named or #Qualifier or any other way to obtain references to actual implementations
private Util defaultImpl;
private Util fallbackImpl;
#Autowired
private DelegatingUtil switcher;
public void switchToFallback(){
this.switcher.setDelegate(this.fallbackImpl);
}
Note, this is only schematic example, you should take care about details like bean creation order, injection with qualifiers (maybe conditional), initialization and so on.
Here is a simple approach based on your situation. The main idea is that read active.util property from DB by PropertyService and wrap your Utils into RouteUtil:
#Component
public class RouteUtil {
#Autowired
private PropertyService propertyService;
#Qualifier("one")
#Autowired
private Util utilOne;
#Qualifier("two")
#Autowired
private Util utilTwo;
public void getClient() {
if ("one".equals(propertyService.read("active.util"))) {
utilOne.getClient();
} else {
utilTwo.getClient();
}
}
}
and in DemoService:
#Service
public class DemoService {
#Autowired
private RouteUtil util;
// RouteUtil.getClient() ...
}
You can change active.util to select which Util will be used at runtime without restarting the app.
Spring provides you a solution which I personally didn't like. What you can do is declare a
#MyInterface
List<MyIntercase> myimpls
Where MyInterface is your interface and list will contain all the implementations. However, I (since I didn't like this solution) wrote my own solution, where you can have a static factory that is self-populated by all implementations. So you don't have to inject all your implementations but choose them at run-time from a factory either by class name or by custom-defined name. An additional advantage is that the custom-defined name must be unique per factory. So lets say you have some staged process and for each stage you have your own interface and your own factory. So you can have the same custom defined names for your implementations of different interfaces. Say you working with text formats XML, JSON and CSV and have an interface (and related factory) for say stage-1 stage-2 stage-3. So for each stage-X inteface you can have implemetations named JSON, XML and CSV so all you have to do is have a variable called currentType that will hold one of the values - JSON, XML and CSV and for each stage you can use the factory to get the appropriate implementation:
Stage1Handler handler = stage-1-factory.getInstance(currentValue);
Stage2Handler handler = stage-2-factory.getInstance(currentValue);
Stage3Handler handler = stage-3-factory.getInstance(currentValue);
where Stage[X]Handler is your interface. But this is just an additional benifit. My solution is available in Open-source MgntUtils library. The article about this particular fiture could be found here: Non-intrusive access to "Orphaned" Beans in Spring framework Also, I describe this feature in my library javadoc here. The library could be found as Maven artifact and on Github including source code and Javadoc
Using Spring 5, I was puzzled as to how exactly the AnnotationConfigApplicationContext "magically" knows to use the correct implementation of my interface, since the references are to the interface not the implementing class.
Illustration
Note: Irrelevant code such as imports and unrelated behaviour has been ommitted
An interface CleaningTool and two implementing classes Broom and VacuumCleaner, with variations on the interface's method doCleanJob()
public interface CleaningTool {
void doCleanJob();
}
public class Broom implements CleaningTool {
#Override
public void doCleanJob() {
System.out.println("Sweep sweep sweep");
}
}
public class VacuumCleaner implements CleaningTool {
#Override
public void doCleanJob() {
System.out.println("Zoom zoom zoom");
}
}
Then, my AnnotationConfigApplicationContex uses my class AppConfig thusly:
#Configuration
public class AppConfig {
#Bean
public CleaningTool broom(){
return new Broom();
}
#Bean
public CleaningTool vacuum(){
return new VacuumCleaner();
}
}
Finally, in my MainApp class, where I invoke the AnnotationConfigApplicationContext's getBean() method, is where I tested this puzzling phenomenon which I, at first, expected not to work:
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);
vacuum.doCleanJob();
}
}
Console output: Zoom zoom zoom
Even though my reference types in both my AppConfig and MainApp were CleaningTool, Spring somehow knew to seek out the Bean that matched the class VacuumCleaner.class, in such a way that the VacuumCleaner's behaviour was used.
How does this "magic" work?
#Configuration is meant to provide a tool to define beans.
Spring creates these beans (instances of classes) and stores them in the ApplicationContext.
You can think of the Application Context as a map that contains mapping between ids / classes of actual beans to the actual instances of corresponding singletons.
So when spring starts it creates both Broom and VacuumCleaner and places both of these beans into application context.
Then the application context is "ready" and you call the following line:
CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);
Note, that you don't ask for the interface CleaningTool but for concrete class VacuumCleaner. In this case spring goes to its internal mappings and just retrieves the value (actual object) by concrete class. No magic here :)
In a java-spring web-app I would like to be able to dynamically inject beans.
For example I have an interface with 2 different implementations:
In my app I'm using some properties file to configure injections:
#Determines the interface type the app uses. Possible values: implA, implB
myinterface.type=implA
My injections actually loaded conditionally relaying on the properties values in the properties file. For example in this case myinterface.type=implA wherever I inject MyInterface the implementation that will be injected will be ImplA (I accomplished that by extending the Conditional annotation).
I would like that during runtime - once the properties are changed the following will happen (without server restart):
The right implementation will be injected. For example when setting myinterface.type=implB ImplB will be injected where-ever MyInterface is used
Spring Environment should be refreshed with the new values and re-injected as well to beans.
I thought of refreshing my context but that creates problems.
I thought maybe to use setters for injection and re-use those setters once properties are re-configured. Is there a working practice for such a requirement?
Any ideas?
UPDATE
As some suggested I can use a factory/registry that holds both implementations (ImplA and ImplB) and returns the right one by querying the relevant property.
If I do that I still have the second challenge - the environment. for example if my registry looks like this:
#Service
public class MyRegistry {
private String configurationValue;
private final MyInterface implA;
private final MyInterface implB;
#Inject
public MyRegistry(Environmant env, MyInterface implA, MyInterface ImplB) {
this.implA = implA;
this.implB = implB;
this.configurationValue = env.getProperty("myinterface.type");
}
public MyInterface getMyInterface() {
switch(configurationValue) {
case "implA":
return implA;
case "implB":
return implB;
}
}
}
Once property has changed I should re-inject my environment. any suggestions for that?
I know I can query that env inside the method instead of constructor but this is a performance reduction and also I would like to think of an ider for re-injecting environment (again, maybe using a setter injection?).
I would keep this task as simple as possible. Instead of conditionally load one implementation of the MyInterface interface at startup and then fire an event that triggers dynamic loading of another implementation of the same interface, I would tackle this problem in a different way, that is much simpler to implement and maintain.
First of all, I'd just load all possible implementations:
#Component
public class MyInterfaceImplementationsHolder {
#Autowired
private Map<String, MyInterface> implementations;
public MyInterface get(String impl) {
return this.implementations.get(impl);
}
}
This bean is just a holder for all implementations of the MyInterface interface. Nothing magic here, just common Spring autowiring behavior.
Now, wherever you need to inject a specific implementation of MyInterface, you could do it with the help of an interface:
public interface MyInterfaceReloader {
void changeImplementation(MyInterface impl);
}
Then, for every class that needs to be notified of a change of the implementation, just make it implement the MyInterfaceReloader interface. For instance:
#Component
public class SomeBean implements MyInterfaceReloader {
// Do not autowire
private MyInterface myInterface;
#Override
public void changeImplementation(MyInterface impl) {
this.myInterface = impl;
}
}
Finally, you need a bean that actually changes the implementation in every bean that has MyInterface as an attribute:
#Component
public class MyInterfaceImplementationUpdater {
#Autowired
private Map<String, MyInterfaceReloader> reloaders;
#Autowired
private MyInterfaceImplementationsHolder holder;
public void updateImplementations(String implBeanName) {
this.reloaders.forEach((k, v) ->
v.changeImplementation(this.holder.get(implBeanName)));
}
}
This simply autowires all beans that implement the MyInterfaceReloader interface and updates each one of them with the new implementation, which is retrieved from the holder and passed as an argument. Again, common Spring autowiring rules.
Whenever you want the implementation to be changed, you should just invoke the updateImplementations method with the name of the bean of the new implementation, which is the lower camel case simple name of the class, i.e. myImplA or myImplB for classes MyImplA and MyImplB.
You should also invoke this method at startup, so that an initial implementation is set on every bean that implements the MyInterfaceReloader interface.
I solved a similar issue by using org.apache.commons.configuration.PropertiesConfiguration and org.springframework.beans.factory.config.ServiceLocatorFactoryBean:
Let VehicleRepairService be an interface:
public interface VehicleRepairService {
void repair();
}
and CarRepairService and TruckRepairService two classes that implements it:
public class CarRepairService implements VehicleRepairService {
#Override
public void repair() {
System.out.println("repair a car");
}
}
public class TruckRepairService implements VehicleRepairService {
#Override
public void repair() {
System.out.println("repair a truck");
}
}
I create an interface for a service factory:
public interface VehicleRepairServiceFactory {
VehicleRepairService getRepairService(String serviceType);
}
Let use Config as configuration class:
#Configuration()
#ComponentScan(basePackages = "config.test")
public class Config {
#Bean
public PropertiesConfiguration configuration(){
try {
PropertiesConfiguration configuration = new PropertiesConfiguration("example.properties");
configuration
.setReloadingStrategy(new FileChangedReloadingStrategy());
return configuration;
} catch (ConfigurationException e) {
throw new IllegalStateException(e);
}
}
#Bean
public ServiceLocatorFactoryBean serviceLocatorFactoryBean() {
ServiceLocatorFactoryBean serviceLocatorFactoryBean = new ServiceLocatorFactoryBean();
serviceLocatorFactoryBean
.setServiceLocatorInterface(VehicleRepairServiceFactory.class);
return serviceLocatorFactoryBean;
}
#Bean
public CarRepairService carRepairService() {
return new CarRepairService();
}
#Bean
public TruckRepairService truckRepairService() {
return new TruckRepairService();
}
#Bean
public SomeService someService(){
return new SomeService();
}
}
By using FileChangedReloadingStrategy your configuration be reload when you change the property file.
service=truckRepairService
#service=carRepairService
Having the configuration and the factory in your service, let you can get the appropriate service from the factory using the current value of the property.
#Service
public class SomeService {
#Autowired
private VehicleRepairServiceFactory factory;
#Autowired
private PropertiesConfiguration configuration;
public void doSomething() {
String service = configuration.getString("service");
VehicleRepairService vehicleRepairService = factory.getRepairService(service);
vehicleRepairService.repair();
}
}
Hope it helps.
If I understand you correctly then the goal is not to replace injected object instances but to use different implementations during interface method call depends on some condition at run time.
If it is so then you can try to look at the Sring TargetSource mechanism in combination with ProxyFactoryBean. The point is that proxy objects will be injected to beans that uses your interface, and all the interface method calls will be sent to TargetSource target.
Let's call this "Polymorphic Proxy".
Have a look at example below:
ConditionalTargetSource.java
#Component
public class ConditionalTargetSource implements TargetSource {
#Autowired
private MyRegistry registry;
#Override
public Class<?> getTargetClass() {
return MyInterface.class;
}
#Override
public boolean isStatic() {
return false;
}
#Override
public Object getTarget() throws Exception {
return registry.getMyInterface();
}
#Override
public void releaseTarget(Object target) throws Exception {
//Do some staff here if you want to release something related to interface instances that was created with MyRegistry.
}
}
applicationContext.xml
<bean id="myInterfaceFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="MyInterface"/>
<property name="targetSource" ref="conditionalTargetSource"/>
</bean>
<bean name="conditionalTargetSource" class="ConditionalTargetSource"/>
SomeService.java
#Service
public class SomeService {
#Autowired
private MyInterface myInterfaceBean;
public void foo(){
//Here we have `myInterfaceBean` proxy that will do `conditionalTargetSource.getTarget().bar()`
myInterfaceBean.bar();
}
}
Also if you want to have both MyInterface implementations to be Spring beans, and the Spring context could not contains both instances at the same time then you can try to use ServiceLocatorFactoryBean with prototype target beans scope and Conditional annotation on target implementation classes. This approach can be used instead of MyRegistry.
P.S.
Probably Application Context refresh operation also can do what you want but it can cause other problems such as performance overheads.
This may be a duplicate question or at least very similar, anyway I answered this sort of question here: Spring bean partial autowire prototype constructor
Pretty much when you want a different beans for a dependency at run-time you need to use a prototype scope. Then you can use a configuration to return different implementations of the prototype bean. You will need to handle the logic on which implementation to return yourself, (they could even be returning 2 different singleton beans it doesn't matter) But say you want new beans, and the logic for returning the implementation is in a bean called SomeBeanWithLogic.isSomeBooleanExpression(), then you can make a configuration:
#Configuration
public class SpringConfiguration
{
#Bean
#Autowired
#Scope("prototype")
public MyInterface createBean(SomeBeanWithLogic someBeanWithLogic )
{
if (someBeanWithLogic .isSomeBooleanExpression())
{
return new ImplA(); // I could be a singleton bean
}
else
{
return new ImplB(); // I could also be a singleton bean
}
}
}
There should never be a need to reload the context. If for instance, you want the implementation of a bean to change at run-time, use the above. If you really need to reload your application, because this bean was used in constructors of a singleton bean or something weird, then you need to re-think your design, and if these beans are really singleton beans. You shouldn't be reloading the context to re-create singleton beans to achieve different run-time behavior, that is not needed.
Edit The first part of this answer answered the question about dynamically injecting beans. As asked, but I think the question is more of one: 'how can I change the implementation of a singleton bean at run-time'. This could be done with a proxy design pattern.
interface MyInterface
{
public String doStuff();
}
#Component
public class Bean implements MyInterface
{
boolean todo = false; // change me as needed
// autowire implementations or create instances within this class as needed
#Qualifier("implA")
#Autowired
MyInterface implA;
#Qualifier("implB")
#Autowired
MyInterface implB;
public String doStuff()
{
if (todo)
{
return implA.doStuff();
}
else
{
return implB.doStuff();
}
}
}
You can use #Resource annotation for injection as originally answered here
e.g.
#Component("implA")
public class ImplA implements MyInterface {
...
}
#Component("implB")
public class ImplB implements MyInterface {
...
}
#Component
public class DependentClass {
#Resource(name = "\${myinterface.type}")
private MyInterface impl;
}
and then set the implementation type in properties file as -
myinterface.type=implA
Be aware that - if interesting to know about - FileChangedReloadingStrategy makes your project highly dependent on the deployment conditions: the WAR/EAR should be exploded by container and your should have direct access to the file system, conditions that are not always met in all situations and environments.
You can use Spring #Conditional on a property value. Give both Beans the same name and it should work as only one Instance will be created.
Have a look here on how to use #Conditional on Services and Components:
http://blog.codeleak.pl/2015/11/how-to-register-components-using.html
public abstract class SystemService {
}
public class FooSystemService extends FileSystemService {
}
public class GoSystemService extends FileSystemService {
}
#Configuration
public class SystemServiceConf {
#Bean
#Conditional(SystemServiceCondition.class)
public SystemService systemService(#Value("${value.key}") value) {
switch (value) {
case A:
return new FooSystemService();
case B:
return new GoSystemService();
default:
throw new RuntimeException("unknown value ");
}
}
}
public class SystemServiceCondition implements Condition {
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}
I'm new to Google Guice and understand Dependency Injection conceptually, but am running into issues trying to incorporate it into my application. My specific question is around Singleton objects. Here's an example:
First, my Module class, which binds a heavy Singleton Connection interface to its implementation.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Connection.class).to(MyConnection.class).asEagerSingleton();
}
}
Now, in my main method, I instantiate my application server and inject the Connection:
public class MyApplication {
#Inject
public MyApplication(Connection cxn) {
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new MyModule());
MyApplication app = injector.getInstance(MyApplication.class);
// Start application, add ShutdownHook, etc...
}
}
Everything good so far... Now, I have some DAO classes that leverage my Connection object, but are retrieved with static methods like so:
public class MyConfiguration {
private Config conf;
private Connection cxn; // Would like to have this injected
private MyConfiguration(Config conf) {
this.conf = conf;
}
public static MyConfiguration getConfig(String name) {
return new MyConfiguration(cxn.getConfig(name));
}
}
My first assumption was that I would simply add #Inject to cxn but this doesn't work because I am not getting the instance from Guice; it just gives me a NPE. The way I see it, I have 2 options for getting the Connection object:
Expose a getConnection() method in MyApplication essentially following the Service Locator Pattern
Add requestStaticInjection(MyConfiguration) to MyModule
I opted for #2, however the docs say:
This API is not recommended for general use
What is best practice for providing my Singleton to the classes that need it without having to go through Injector.getInstance each time? What am I missing?
You're thinking about dependency injection incorrectly. Dependency Injection and Service Locator are mirror-images of each other: with a service locator, you ask it for an object. With dependency injection, you don't go looking for dependencies, they're just handed to you.
Basically, "it's turtles all the way down"! Every dependency your class has should be injected. If MyApplication needs a MyConfiguration object, it should just accept a MyConfiguration object as a constructor parameter, and not worry about how it was constructed.
Now, this isn't to say that you can never use new manually -- but you should reserve that for value-type objects that don't have external dependencies. (And in those cases, I'd argue that you're often better off with a static factory method than a public constructor anyway, but that's beside the point.)
Now there are a couple of ways of doing this. One way is to shard MyConfiguration into lots of tiny pieces, so that instead of doing myConfiguration.getConfig("x") you would do #Inject #Configuration("x") String or something like that. Alternatively, you could make MyConfiguration itself injectable, and then provide accessor methods on it for the pieces. The right answer depends somewhat on the kind of data you're trying to model -- make the dependencies too fine-grained and your bindings may become hard to maintain (although there are ways to make that better); make the dependencies too coarse and you make it harder to test (for example: which is easier, providing just the "x" config that the class you're testing needs, or building the whole application's config?).
You can even do both:
/** Annotates a configuration value. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
public #interface Config {
String value();
}
/** Installs bindings for {#link MyConfiguration}. */
final class MyConfigurationModule extends AbstractModule {
#Override protected void configure() {}
#Provides
#Singleton
MyConfiguration provideMyConfiguration() {
// read MyConfiguration from disk or somewhere
}
#Provides
#Config("x")
String provideX(MyConfiguration config) {
return config.getConfig("x").getName();
}
}
// elsewhere:
/** The main application. */
final class MyApplication {
private final String xConfig;
#Inject MyApplication(#Config("x") String xConfig) {
this.xConfig = xConfig;
}
// ...
}
You can take a similar approach in unit tests:
/** Tests for {#link MyApplication}. */
#RunWith(JUnit4.class)
public final class MyApplicationTest {
// Note that we don't need to construct a full MyConfiguration object here
// since we're providing our own binding, not using MyConfigurationModule.
// Instead, we just bind the pieces that we need for this test.
#Bind #Config("x") String xConfig = "x-configuration-for-test";
#Before public void setUp() {
// See https://github.com/google/guice/wiki/BoundFields
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
#Inject MyApplication app;
#Test public void testMyApp() {
// test app here
}
}
Dependency injection also encourages another best practice which I highly recommend, which is to design your type system such that invalid states are not representable (to the maximal degree possible). If all the configuration MyApplication needs is passed in its constructor, it's impossible to ever have a MyApplication object that doesn't have a valid configuration. This allows you to "front-load" your class invariants, which makes it much easier to reason about the behavior of your objects.
Finally, a note about Injector.getInstance(). Ideally you use Injector exactly once in your program: immediately after it is constructed. That is, you should be able to do Guice.createInjector(...).getInstance(MyApplication.class).start() and never store a reference to the Injector anywhere. I tend to build applications using Guava's ServiceManager abstraction (see also this question), so the only thing I ever need to do is:
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(...);
ServiceManager manager = injector.getInstance(ServiceManager.class);
manager.startAsync().awaitHealthy();
}
I'm trying to understand if I can combine reflection with spring dependency injection as the following:
public interface ClientCommand {
public void execute(...);
public static enum Command {
SomeCommand(SomeCommand.class);
private Class<? extends ClientCommand> clazz;
private Command(Class<? extends ClientCommand> clazz) {
this.clazz = clazz;
}
public Class<? extends ClientCommand> getClazz() {
return clazz;
}
public static ClientCommand getClientCommand(String name) {
Command command = Enum.valueOf(Command.class, name);
return command.getClazz().newInstance();
}
}
}
This will create an instance of a command class based on the name passed in getClientCommand.
This is an example of class extending ClientCommand:
public class LoginCommand implements ClientCommand {
#Autowired
private UserRepository userRepository;
public void setUserRepository(#Qualifier("userRepository")UserRepository userRepository) {
this.userRepository = userRepository;
}
public void execute(...) {
...
}
}
And the repository is something like:
#Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
....
}
When the LoginCommand.execute() method is executed, the UserRepository is null.
If I use the newInstance() to create the object, does spring care at all to inject the dependencies?
More than for practical use, is to understand if is theoretically possible to get this code working.
Thanks in advance
To answer this question:
If I use the newInstance() to create the object, does spring care at all to inject the dependencies?
I will answer with no, not by default. Spring will only inject dependencies on objects that Spring is in control of, and if you are using reflection to instantiate it, or the new operator, then you are the one in control, not Spring.
But, there is hope. You can use AspectJ to do bytecode weaving when the new operator is used, or even when Class.newInstance() is used.
Take a look at this Spring documentation for more on this approach.
Since you're creating the object on your own Spring will not do dependency injection on the object. It will also not add any AOP proxies for it if its configured to do that.
You can either use AspectJ to instrument your code by adding the logic necessary to do dependency injection on the instance. This is done completely transparently.
Or you can do it yourself by using AutowireCapableBeanFactory. It's a semi-internal interface that you can use and its intended for just this purpose. It has a set of methods that do various parts of creating and injecting, you'll probably need the createBean() method.
You can get an AutowireCapableBeanFactory by calling getAutowireCapableBeanFactory on your ApplicationContext.
In your case it would probably be a good idea to create a CommandFactory, make that implement ApplicationContextAware and have a method like createCommand() that calls createBean().