Is it possible to make the BeanFactoryPostProcessor detects if beans classes have methods annotated with a custom annotation (#inject for instance) and proceed to make a certain treatment if it's the case ?
If this is not possible, can you explain how i get access to the beans metadata and exploit it in the BeanFactoryPostProcessor ?
Thanks in advance.
Edit: I came across this link, not sure if it's the right solution though, since i heard that using reflections considerably deteriorates the overall application performance.
The ConfigurableListableBeanFactory passed into the postProcessBeanFactory() method call, has a method getBeanDefinition(String), from which you can get the class name of that bean. From here you can do a Class.forName(String), and get the class, and then you can inspect its members for your annotation. Of course this suggestion uses Java Reflection also.
You could also try to annotate each class that you want to inspect with its own custom annotation. From the ConfigurableListableBeanFactory you can then call getBeansWithAnnotation(Class). This returns a map from beanName to the corresponding instance.
Or you can take a look at the JavaDoc yourself:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.html
Related
I have done my research before asking but no luck.
I have a StartUp Singleton bean. In this bean I have an #Inject #Any Instance. I loop all the implementations and try to check if the class is annotated with a custom annotation. All the implementations(all the classes that I want to inspect) are Stateful or Stateless beans.
Sometime the class I want is found and I can perform getClass().isAnnotationPresent(ClassNameAnnotation.class)
Most of the times I get a proxy object and in this case I cannot perform the above check.
I cannot find a way to get the real object. I have tried to get the SuperClass but not luck.
I will attach some of the code so you can have a better idea.
#Singleton
#Startup
public class CacheLoader {
#Inject
#Any
private Instance<ClassNameA> aClasses;
.......
#Lock(LockType.READ)
public void evaluate() {
if (!aClasses.isUnsatisfied()) {
for (ClassNameA className : aClasses) {
if (className.getClass().isAnnotationPresent(ClassNameAnnotation.class)) {
....
}
}
}
}
}
I tried to use the SuperClass of the proxy object but it does not return what I want. I tried also via Proxy.getInvocationHandler(). Even when I check the methods Proxy.isProxyClass(getClass()) or isSynthetic() does not return that the object is a proxy.
Thank you!
I think you would be better served by using a CDI Portable Extension, rather than a Singleton EJB. A couple of reasons
In CDI, everything is a proxy. So like some of the commenters have said, using reflection would be very fragile as it's not part of the spec. You're dealing with classes that are defined at runtime. It may work if you tie yourself to implementation-specific details, but it could break between releases of your CDI container.
The CDI Container will do all of the annotation scanning for you :)
A portable extension runs on startup, before other stuff starts flying around your app
A google search gave me this guide, but there are lots of them: https://www.baeldung.com/cdi-portable-extension
I think you would want to hook in processAnnotatedType() if you're modifying the bean declarations, or afterBeanDiscovery() if you're just documenting them as you said.
We actually have a CDI Portable Extension we use internally that does some config magic for environments. One of the config params is an annotation that is not a qualifier annotation, which sounds like what you want... the CDI container can get you the type, from which you can inspect the annotations.
Finally, this is not directed related to your question but may be useful: If your annotations drive configuration through fields of the annotations, selecting them can be quite complicated because of how the Java type and inheritance system works with annotations. You may benefit by using AnnotationLitreal in those cases. Read up here on this useful utility class here: http://www.kurtsparber.de/?p=387
EDIT:
Another side note... even thought I think you should switch to a Portable Extension, you shouldn't need #EJB's Singleton Startup anymore! you can do this with pure CDI: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/
I want to listen on method calls in order to attach additional behavior dynamically around the call. I've already done it on JUnit methods with a custom annotation and runner. I'm trying to do it on a standard java application.
The main idea is to do:
#Override
public void beforeInvoke (Object self, Method m, Object[] args){
Object[] newargs = modifyArgs (args);
m.invoke (self, newargs);
}
It's just an abstract idea, I don't have any concrete example, but I'm curious if it's possible in java.
I've found some approaches:
java.lang.reflect.Proxy.newProxyInstance(...)
where a proxy is defined for an interface only (but not used to decorate concrete classes). It seems similar to injection pattern and it's a different concern.
Another approach here using a factory pattern with the ProxyFactory class. This other solution requires explicit calls to create() method to produce object proxies listening on method invocations. So, if you bypass it by using natural constructors of your classes, it's not working. It's very constraining if you must explicit a call to a factory each time you have to create an object.
There is a way to do it with transparency ?
Like Proxy.newProxyInstance() but working also on concrete classes ?
Thanks.
Well,this is commonly seen with Spring Framework and Aspect Oriented Programming. Since you delegate your constructor calls to Spring, it is quite easy for Spring to put a proxy in place to intercept calls to the actual objects.
As far as I can tell, the only way to intercept calls is to use a proxy. Either in the way you mentioned or using Spring and AOP.
I think cglib let you instrument concrete classes.
As far as I know there is no easy way to intercept method calls that are called on a concrete class.
As mentioned you could manipulate the bytecode during compilation (as Used in AOP) or at class loading time (as used from cglib).
Another product to instrument Classes would be jmockit (http://jmockit.org/). Usually I would use this special kind of black magic only in testing environments and not in an productive environment.
Another way you could go is Annotation Processing. It work's during compiling process. You have to write a Processor which will walk through your source code and generate source-code that contains the original code plus the enhanced method-calls you need.
Depending on how much source-code you have to enhance, this method might be a good idea, but in general it is a lot of work.
Here's a link (https://deors.wordpress.com/2011/10/08/annotation-processors/).
Despite usually it's used in combination with annotations, this is not a strict requirement.
This might be a strange request but is there a way to access Spring annotation attribute in the method itself.
In the example below one can define "user.success" as a constant and use it in the Annotation and the method but I would really like use whats defined in my annotation(#MySecurity).
One way I guess would be get a handle of the executing method to use AnnotationUtils. Is there a better more elegant way of doing this?
#MySecurity(action="user.success")
#RequestMapping("/userSuccess.htm")
public String redirect()
{
// Code here to access #MySecurity Annotation
return "userSuccess";
}
No, it is not possible without reflection. And even then, you need to know the name of the method. Executing code in it doesn't tell you that (except stack trace but don't go that path). Honestly, the annotation should be used by a HandlerInterceptor (with HandlerMethod where you would have access to the annotation) or some kind of BeanPostProcessor.
I want to be able to call Interfaces in my class, but have spring instantiate them with the right implementation class behind the scenes.
I.e. Normally you can do:
IClass clz = new Class();
I want to have the line IClass clz; preferable in the middle of a method (or as one of the attributes if it can't be done), where clz is instantiated to the class I want by Spring.
The reason I'd like to do it this way is because I want to be able to be able to change which implementation I want to use simply by editing the context files.
Even better, would be knowing how to do the above with class contructors that expect parameters. i.e. new Class(ar1, arg2);
I hope this makes sense. Any help would be much appreciated.
You can make your class implement BeanFactoryAware and then Spring will inject the bean factory in your class. If you then want to get an instance of a class implementing your interface you say something like:
beanFactory.getBean(IClass.class);
If there are multiple beans that implement the same interface you will have to resolve by name. To create a new object each time you ask this, set the bean scope of the bean you're asking for to "prototype".
You can include code such as:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
IClass clz = (IClass) context.getBean("beanName");
Not saying this is better per se than Gerco's answer btw, just it's an option, depending what you want to do.
You can also implement the ApplicationContextAware interface: I've found that using ApplicationContext gives me beans with filled-in properties, e.g. if you have an app.properties file which contains key/value property pairs which you expect to be resolved within the Spring config, beans retrieved via BeanFactory calls may not resolve those.
See this previous SO topic for more info.
I am trying to let a piece of runtime state decide WHICH implementation of an interface to use, preferably solely by autowiring.
I have tried making an object factory for the interface thet uses dynamic proxies, and I used qualifiers to coerce the #Autowired injections to use the factory. The qualifiers are necessary because both the factory and the implementations respond to the same interface.
The problem with this is that I end up annotating every #Autowired reference with the #Qualifier. What I'd really want to do is annotate the non-factory implementations with something like #NotCandidateForAutowiringByInterface (my fantasy annotation), or even better make spring prefer the single un-qualified bean when injecting to an un-qualified field
I may thinking along the totally wrong lines here, so alternate suggestions are welcome.
Anyone know how to make this happen ?
You could use #Resource and specify the bean name of the factory.
I haven't looked at this myself but I noticed Spring JavaConfig is made it to M4 and it seems to allow more flexible configuration through a combination of annotations and Java code. I wonder if it would offer a solution to your problem.