What is the most concise way of making sure that a Spring bean has all properties set and the init method called?
I'll favour answers which use setter injection and XML configuration, since that's what I'm using right now.
I'm trying to evade the case where I either forget to configure a setter or call the init-method.
In future projects I would favour skaffman's response, but I've chosen the one which suits me right now.
This poll is exactly what you are looking for.
Here are the results:
By using the dependency-check attribute in XML: 11.52%
By using the #Required annotation (or a custom annotation): 21.40%
By using InitializingBean and an assert facility: 23.87%
By using init-method and an assert facility: 14.40%
I don't have to, because I use constructor injection for required properties: 19.34%
I check my dependencies in my business methods: 7.41%
I don't check required dependencies: 34.16%
Use the #Required annotation on the setter methods. Spring will then check that they've all been set without you having to check manually.
Alternatively, annotate your init methods with #PostConstruct, and Spring will invoke them for you.
You can add the dependency-check attribute to your bean definition to ensure that all objects / primitives / both have been set.
<bean id="myBean" class="com.foo.MyBean" dependency-check="objects"/>
Skaffman's answer gives more control, but does introduce a compile-time dependency on Spring which you may / may not want.
Use the following attributes of the beans tag to make sure dependency checking and the init method is called on all beans, but it rather assumes you don't call your method "innit".
<beans default-init-method="init" default-dependency-check="objects">
see link
Related
I need to create a means to add a custom annotation like
#Value("${my.property}")
However, in my case I need to get the value from a database rather then a properties file.
Basically I would like to create a bean on container startup that reads in property name value pairs from a database and can then inject these into fields belonging to other beans.
Approach #1:
One way is to create an Aspect, with a point-cut expression that matches any method having this annotation.
Your aspect will then:
Read the property value in the annotation
Look up the required value an inject it into the class.
AOP Kickstart
Here's a guide to getting started with AOP in Spring
http://www.tutorialspoint.com/spring/aop_with_spring.htm
Joinpoint matching
Here's a reference that describes how to create a join-point that matches on annotations: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
Approach #2:
Another way is to use a BeanFactoryPostProcessor - this is essentially how a PropertyPlaceholderConfigurer works.
It will look at your bean definitions, and fetch the underlying class.
It will then check for the annotation in the class, using reflection.
It will update the bean definition to include injecting the property as per the value in the annotation.
. . actually I think approach #2 sounds more like what you want - all of the processing happens on "start-up". . . (In actual fact your modifying the bean recipes even before startup). . whereas if you used AOP, you'd be intercepting method invocations, which might be too late for you?
Namespace Handler
If you wanted you could even create your own Spring namespace handler to turn on your post processor in a terse way. Eg:
<myApp:injectFromDb />
as an alternative to:
<bean class="MyDatabaseLookupProcessorImpl etc, etc. />
Update: Approach #3
As of Spring 3.1 there's also the PropertySourcesPlaceholderConfigurer, that will provide most of the plumbing for you, so you can achieve this with less code.
Alternatively you should be able to configure kind of properties repository bean and then use it in SpEL directly in #Value annotation.
Let's say you'd have bean called propertiesRepository in your context that implements following interface:
interface PropertiesRepository {
String getProperty(String propertyName);
}
then on bean where you want to inject values you can use following expression
#Value("#{propertiesRepository.getProperty('my.property')}")
String myProperty;
You can use #Value annotation by injecting database configuration in application environment itself.
I know this is an old question but I didn't find an exact solution. So documenting it here.
I have already answered the same on different forum.
Please refer to this answer for exact solution to your problem.
I read about the advantages of using Dependency for interface.
I understand the concept for interface - but why to use #Autowire on class? If we use Autowire on class I know in advance what is the implmeneted class and it's like a regular member of it (without the ability of get to this member)!
What am I missing?
1) Convenience - you do not need to take care for initializing your components, you save time on typing code and configuration files,
2) Forcing good practices - your components to be autowired must be written to be manageable by Spring and spring will take care about error checking for you and pop all errors. So your code will be organized in component collaborating way.
3) Autowiring will also reduce your effort when your classes/beans will grow and evolve.
If you use #Autowire and not call the constructor, you mark the class to be dynamically initialized by the Spring Container. This allows you to set class properties as defined in your spring configuration.
If we use Autowire on class I know in
advance what is the implmeneted class
and it's like a regular member of it
When you wire the dependency through XML instead of Annotations, you also know in advance in which class are you going to inject it.
But You still declare an Interface as dependency, so you can wire any Implementation of this interface at runtime.
Is there a way to use Spring lookup method inject with parameters? For example, I want to be able to instantiate prototype-scoped beans while passing them arbitrary parameters via constructor.
It looks like this vital feature was finally added in Spring 4.1.0.RC2. I have tested it and it seems to work.
It was added as part of JIRA ticket SPR-7431 ("Passing lookup-method arguments to created bean constructor"):
<lookup-method/> should allow specifying any number of parameters. These parameters should be passed directly to the constructor of the newly created bean.
For more info on how the feature was finally added, this blog post was written by the guy who opened the JIRA ticket.
You can inject them via field/setter injection. (Note that constructor injection is frowned upon by spring, although it's supported)
in short, no. Spring does support something called "method injection" but it's different than you're thinking. Spring also supports constructor injection, but then you're not calling the constructor yourself, Spring is, and wiring it itself.
Instead, you can use reflection to instantiate the class and pass arbitrary parameters yourself:
Class<MyObject> clazz = MyObject.class; // this can be looked up or stored in a field, etc.
MyObject myObject = clazz.getConstructor(String.class, int.class)
.newInstance("arbitrary parameter", 42);
This is a basic question - when spring bean is loaded and if i have a constructor and setters which one will be called first?
Thanks
The constructor must be called before any setter methods are called. Use the init-method to tell Spring to invoke some logic after the setters are called:
<bean class="my.CoolClass" init-method="startup">
<constructor-arg value="Foo" />
<property name="bar" value="baz" />
</bean>
Doesn't the constructor have to be called first? The setters are instance methods so that can't called until the object is instantiated.
I don't think Spring provides any guarantees about the order in which setters are called. It would be good practice to make your beans work regardless of which order the setters are called. If you want to do some processing after all the setters have been called, you might find that it's convenient to use a post construction method. Or if you are using XML configuration rather than annotations, an initialization method might suit.
I wrote simple XML config and step through Spring source code in debugger.
Seems that with Spring 3.x it's possible to combine constructor-arg and property in XML bean definition (check doCreateBean in AbstractAutowireCapableBeanFactory.java, which call createBeanInstance - constructor and populateBean next - setters).
See also https://softwareengineering.stackexchange.com/questions/149378/both-constructor-and-setter-injection-together-in-spring/
I'm trying to use Spring AOP to inject behavoir into an object. The target object has a single method which is the join point for this new behavior. That method also has a custom annotation that I want to be able to read from other unrelated code. Because my class doesn't implement an interface, Spring is using CGLIB to dynamically subclass the target object. The generated subclass doesn't seem to have the annotation added to the original class.
I tried adding the #Inherited annotation to the custom annotation without luck. It turns out #Inherited only applies to classes. This suggests that Spring would have to explicitly apply my annotation to the overridden method in the subclass.
EDIT: I found a workaround and some more information on the problem. It looks like the CGLib people are aware of the issue. Annotations are treated like implementation in Java (rather than like part of the method signature). Overriding methods must re-declare annotations. CGLib doesn't do this (intentionally by the sound of things).
My workaround was to change my reflection logic. Where I was searching for the annotated method on the class passed to me, I now look at the class and it's super classes. I end up locating the method using the superclass (in the case of a proxy), but when I call the method, regular polymorphisim applies. This makes for some ugly reflection code (even more ugly than normal). It also seems like I shouldn't have to compensate for a SpringAOP implementation detail in my code.
It seems like Spring should provide a cleaner way to handle this. If anyone has other suggestions, they would be appreciated.
Are you sure you have the RetentionPolicy on your annotation set to RUNTIME ?