I have a spring bean that extends HibernateDaoSupport. I want this bean injected into my Controllers, but I do NOT want it to implement any interface. I just want to refer to the concrete class from within the rest of my code (not use the AopProxy perhaps?) Does anyone have a way of doing this?
<bean id="mySampleService" class="com.sample.MySampleService">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
#Autowired
private MySampleService mySampleService;
... getters and setters ....
I know it's a good idea to use the interface and that's the whole point of IoC, but PLEASE DON'T suggest I use the interface.
If class to be proxied (by transactional proxy in your case) implements any interface (InitializingBean implemented by HibernateDaoSupport in your case), Spring by default uses proxying strategy based on JDK dynamic proxies.
So, it creates a proxy of type InitializingBean, that, obviously, cannot be injected into a field of type MySampleService.
If you don't want to use interface you can override the strategy used by transactional aspect by declaring <tx:annotation-driven> with proxy-target-class = "true".
See also:
7.6 Proxying mechanisms
Check the following. Ensure you have CGLIB on your classpath.
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch08s06.html
you can write everything including the mapped controller in the xml as beans, then you don't need to write interfaces.
otherwise, with using annotation you need to build interfaces to proxy them.
Related
I want to find analog #PostConstruct spring annotation for external bean.
I don't have oportunity to change source code of this class and this class is final.
other words: how to invoke external method after bean constructing?
You can try init-method, i.e.:
<beans>
<bean id="yourBean" class="com.example.your.external.Class" init-method="yourExternalInitMethod"/>
</beans>
EDIT
Alternative solution might be implementing InitializingBean, but it's Spring-specific interface.
EDIT2.
You might want to take a look at Mkyong's tutorial about init-method and destroy-method.
If you can't change this class nor derive it, maybe a customized BeanPostProcessors would do the job ?
Here is my Spring AOP configuration.
<bean id="myObject" class="com.madzone.learn.spring.aop.OriginalClass"></bean>
<bean id="aspect" class="com.madzone.learn.spring.aop.AspectClass"></bean>
<aop:config>
<aop:aspect ref="aspect">
<aop:declare-parents
types-matching="com.madzone.learn.spring.aop.OriginalClass+"
implement-interface="com.madzone.learn.spring.aop.IntroducedInterface"
default-impl="com.madzone.learn.spring.aop.IntroducedInterfaceImpl" />
</aop:aspect>
ApplicationContext context = new ClassPathXmlApplicationContext("myApp.xml");
Object myObject = context.getBean("myObject");
if (myObject instanceof OriginalClass) {
System.out.println("This is OriginalClass");
}
if(myObject instanceof IntroducedInterface) {
System.out.println("This is IntroducedInterface");
}
With this introduction I was able to call the methods in the IntroducedInterface. But, I was not able to access the OriginalClass' methods. In the code snippet above, I never got the 'This is OriginalClass' printed out.
From the definition of 'Introduction' I understood that the proxy that implements the new interface will extend from OriginalClass and make its' methods accessible too.
Am I missing something here? Can someone explain the reasons, if any?
PS:
The following is a picture from Spring in Action (3rd Edition) that depicts this.
From the definition of 'Introduction' I understood that the proxy that
implements the new interface will extend from OriginalClass and make
its' methods accessible too.
I'm not sure where you got that impression from. All of Spring AOP is built, by default, on JDK dynamic proxies, which only work for interfaces. It's impossible to proxy a concrete class. There is support in Spring for using CGLIB proxies in order to proxy classes instead, but its use is discouraged by the reference guide in favor of programming to interfaces to reduce coupling.
Ok, so here is my use case:
I have the following classes each encapsulating an instance of the next one in line. So:
A -> B -> C -> D
eg: In class A, I have an instance of class B and in class B I have an instance of C and so on.
Well, I am trying to convert the loading\initialization\injection logic to a hybrid Spring system. The general idea being that B, C and D will need to more or less be ApplicationContextAware. By that I mean, that they will not actually implement that interface, but instead require the ApplicationContext as a constructor parameter. This way, in the hybrid approach (where the developer does not use Spring to initialize the instance) they must at least pass in the ApplicationContext so that additional beans may be wired. The problem is, that in order for the Spring container to load the beans, I now have to pass in the ApplicationContext in the XML. But as far as I can tell, there is no nice way to do this.
I tried something like this:
public class ApplicationContextPlaceholder implements ApplicationContextAware {
private ApplicationContext _applicationContext;
public void setApplicationContext( final ApplicationContext applicationContext ) throws BeansException {
_applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return _applicationContext;
}
}
<bean id="a" class="com.company.A">
<constructor-arg>
<bean id="applicationContext" class="com.company.ApplicationContextPlaceholder" />
</constructor-arg>
</bean>
But obviously this doesn't make any sense, since ApplicationContextPlaceholder isn't really an ApplicationContext. I've also looked for ways to reference the context inside the XML, but I'm not finding anything.
Does anyone know of an elegant solution to this type of problem?
EDIT #1:
I was thinking about it, and I could have ApplicationContextPlaceholder also implement ApplicationContext and just delegate to the injected context and then it occurred to me that maybe, just maybe this was already in Spring...but as far as I can tell, no.
EDIT #2:
The reason each class needs an ApplicationContext is that if a dev wishes to override one of the classes in the chain (say, C for sake of argument). In this instance the child class of C will still need to load D via Spring.
Unless a class is providing additional plumbing functionality, you should avoid exposing the ApplicationContext. Quoting the Spring reference: in general you should avoid it, because it couples the code to Spring and does not follow the Inversion of Control style.
If you are providing additional functionality (maybe, for example, a factory class that uses the ApplicationContext to assemble objects), then it's prudent to implement ApplicationContextAware since your functionality is already tied to Spring.
If you've considered your dependency injection alternatives and have decided on injecting the ApplicationContext in your beans, your ApplicationContextPlaceholder class (I would stay away from a Placeholder prefix to avoid any confusion with Spring property placeholders) is certainly a solution. (Since it is your own class, why not extend ApplicationObjectSupport for additional functionality.)
This class will need to be defined and initialized in your configuration, for example:
<bean id="appCtxHolder" class="ApplicationContextHolder" />
Because ApplicationContextHolder implements ApplicationContextAware, Spring will inject the ApplicationContext into appCtxHolder when it is initialized. You can use it for constructor injection like:
<bean id="a" class="com.company.A">
<constructor-arg>
<bean factory-bean="appCtxHolder" factory-method="getApplicationContext" />
</constructor-arg>
</bean>
ApplicationContextPlaceholder could have everything static. In that case, you don't need to pass ApplicationContext around, when a API requests for a certain bean, you could check if its null and if it is, load it using the ApplicationContext from ApplicationContextPlaceholder. That's assuming a setter based injection, if you are doing constructor based, you could init beans in the contructor too.
Say that I have class Controller with property strategy of type IStrategy. In Spring, I can create different instances of Controller and inject different strategy implementations by defining beans in xml configuration file as shown below:
<bean id="strategyAController" class="com.test.Controller">
<property name="strategy" ref="strategyAImpl">
</bean>
<bean id="strategyBController" class="com.test.Controller">
<property name="strategy" ref="strategyBImpl">
</bean>
<bean id="strategycController" class="com.test.Controller">
<property name="strategy" ref="strategycImpl">
</bean>
I can then reference these beans using #Autowired and #Qualifier("strategyAController"), etc. What is the equivalent way of doing this in Java EE 6
Funny you should ask! Gavin King, who designed Java EE 6 CDI, got into a nasty fight with someone on exactly the same problem.
http://www.tsolak.com/?p=59
The Spring code, of course, looks awfully like Java. We can do that in java - create some variables, set some properties, no biggie. I am curious, in your perticular application, what's the drawback of doing it in plain Java? What's the specific benefit you get from Spring for these beans?
In CDI you can use Qualifer to identify the different instances and producer methods to provide that instances.
public class ControllerFactory {
#Produces
#StrategyA
public Controller createControllerA {
return new Controller(configA);
}
#Produces
#StrategyB
public Controller createControllerB {
return new Controller(configB);
}
}
#StrategyB
#Inject
Controller howToAccessIt;
If you do not like to create a new StrategyA/B/C Annotation for each strategy, you could use one Annotation with an Field (for example an Enum) that identify the strategy. So that you can write: #Strategy(StratType.A).
Then you can use the InjectionPoint in your producer method, so that you can create the instance depending on the annotation in a generic way, instead of writing a new producer method for each Strategy:
#Produces
//must add a Annotation to clarify that this producer produces for all Strategies!
public Controller createController(InjetionPoint ip) {
Annotated annotated = ip.getAnnotated();
if (annotated.isAnnotationPresent(Strategy.class)) {
Strategy stragtegyAnnotation = (Strategy) annotated.getAnnotation(Strategy.class);
switch(stragtegyAnnotation.value) {
case A: return new Controller(configA);
...
}
}
}
So, I'm not really familiar with EE6 annotations, but I solved a similar issue using pure Spring annotations in a question that I asked and then answered myself. It's not quite the same thing because it only creates once instance, but with all of the different dependencies injected into a Map. Basically, it will allow to switch implementations based on a config flag, but not instantiate all of them at once.
How does Wicket's #SpringBean annotation work? Does it use reflection at run time? Does it make the compiler inject some code? Or what?
#SpringBean works using Wicket's underlying Injector mechanism. When you instantiate a Wicket component, the constructor of Wicket's component base class introspects the class being instantiated, looking for the #SpringBean annotation. If the bean is found, then Wicket generates a proxy for the spring bean and injects it into the component's field. This is Wicket's equivalent of Spring's #Autowired annotation, the effect is similar.
It doesn't, however, have anything to do with Spring's own context/classpath scanning functionality (e.g. #Component), which is about auto-discovery of what is and isn't a bean, rather having anything to do with wiring.
The class marked with a #SpringBean annotation has to have one of:
A no-args constructor
A superclass with a no-args constructor
Implement an interface
An exception will be thrown if these conditions are not met as Wicket will not be able to proxy the class.
Spring uses the class loader and ASM at runtime to find all annotated classes.
You can configure where spring should search for beans:
<context:component-scan base-package="some.package.to.start.from"/>
This uses the ClassPathBeanDefinitionScanner internally which will use the PathMatchingResourcePatternResolver to find the classes and the ASM-based MetadataReader to read the annotations.