I've declared my aspects using the #Aspect annotation, but the advice does not seem to get applied. The aspect works in a few other projects that I have, and the key difference seems to be that the other projects are completely wired using annotations, and this particular project is xml wired. The only bean that is annotation wired is the Aspect. So I'm wondering if spring's aspectj support, when using aspectj-autoproxy is sensitive to order that the beans are defined in the xml.
For example, will beans declared after aspectj-autoproxy in xml be considered for AOP pointcuts?
EDIT:
I moved the <aop:aspectj-autoproxy /> until after all beans are created and still no luck.
Basically my code consists of:
#Component
#Aspect
public class SomeAspect {
#Pointcut("#annotation(MyAnnotation)")
public void isX() {}
#After("isX()")
public void XX() {
System.out.println("Called aspect");
}
}
And my controller has something like:
public class XController extends AbstractCommandController {
#MyAnnotation
public void handleX(...) {
// do stuff
}
#Override
protected void handle(...) {
return handleX(...);
}
}
And then the spring xml is:
<context:component-scan base-package="package.of.some.aspect" />
<aop:aspectj-autoproxy />
<!-- the rest of the beans below -->
<bean id="someController" class="..." />
My previous projects captured and loaded all beans via the component-scan. That's what's different this time.
EDIT2:
The other difference is that the other projects are using #Controller, and #RequestMethod. And in this case I'm using a derived class of AbstractCommmandController. I'm wondering if this applies:
http://forum.springsource.org/archive/index.php/t-46637.html
Namely that I can't apply advice to any method except handleRequest().
EDIT3:
My latest try is to override handleRequest() and apply my annotation there. Under the assumption that when spring proxies my controller it will see the annotation and apply the advice, since it's calling through the public, externally called method. This still doesn't work.
I see that you are calling the method handleX directly from another method in the same class. This will not respect the annotiation, as the work of processing AOP annotations is done by a JDK proxy that wraps your class and exposes the same interfaces.
It's possible that you can work around this by using CGLIB instead of JDK proxies, but in my experience, the most reliable solution is just not to rely on any AOP annotations for methods called internally.
Related
I want to use data mappers, logger, transfromers, etc. in my Spring web projects. Is it possible to autowire an imported (jar) utility dependency, without wrapping it in some #Component or #Service class? Do we even want to do it that way, or should we just use a static reference?
If your utils, are based on not static methods, then this is simple:
If you use java based configuration, then just declare that util in an #Bean annotated method.
#Configuration
public class YourConfig {
#Bean
public YourUtil util(){
return new YourUtil ();
}
}
in xml it could been as simple as:
<bean id="util" class="org.example.YourUtil" />
The following is true, but it is not what was asked for:
There are at least two other ways to inject beans in instances that are not created (managed) by Spring:
(1) add #Configurable annotation to this class - this requires real AspectJ (compile-time or load-time -weaving)
#see Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
#see this answer of mine https://stackoverflow.com/a/7007572/280244 for a quick "guide" to enable the #Configurable support
(2) invoke SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
#see this question and its (two highes voted answers) for some ideas how to use
You can only #Autowire a bean managed by Spring. So you have to declare your instance through some configuration : a bean in an xml file, or a #Bean method in a java configuration.
#Component are just automatically discovered and registered in the spring context.
I'm new to Spring AOP, and I've to know if it's possible to implement my project with Spring AOP. Specifically, I want to know if in Spring AOP it's possible to configure, at runtime, which aspects will be executed and in which order. NB: I want to control only mine application aspects', without interfering with Spring-managed aspects like transactions or security.
You can control the ordering of aspesct (using declare precedence), but its hard to do this at run time, as it would need to reapply the weaving for already weaved classes.
The same goes for specifying which aspects to execute.
You could have an if(!enabled){return;} check at the start of each aspect method, and the enabled flag could be set on or off just like any normal bean. This way, the aspects are always weaved in, but they will do nothing if they are disabled.
UPDATE
Here is example of how to use an aspect as a bean.
Lets say you have an aspect like this:
#Component // IMPORTANT
public aspect MyAspect {
Object responder;
public void setResponder(Object object) {
this.responder=object;
}
}
Then in your spring service class, you can wiring the aspect like this:
#Service
public class MyServiceImpl implements MyService {
#Autowired
MyAspect aspect;
void action() {
aspect.setResponder(null);
}
}
This works because aspects are actually java classes. The component annotation causes the aspect to be recognised as a bean by the spring component scan.
I have compiled this code successfully, but not actually tested it runtime, so would be good to know if it works.
public interface Service {
public void doSomething();
}
#Service
public class MyService implements service{
#Transactional
public void doSomething(){
}
}
#Controller
public class MyController {
#Autowired
private MyService service;
}
In above scenario autowiring fails with exception "illegalArgumentException : argument type mismatch". When I remove implements service from MyService everything works fine.
I have searched and found that place <aop:aspectj-autoproxy proxy-target-class="true"/> in applicationContext.xml for successful autowiring and it worked.
I have also found that spring uses JDK proxy when #Transactional is used.
I have some confusions,
How #Transactional relates to Proxying
Why spring uses JDK Proxy for the beans which implements interfaces.
Why I need to place <aop:aspectj-autoproxy proxy-target-class="true"/> in applicationContext.xml
Can anyone please explain ? or refer me any article or blog
Proxying is how Spring implements declarative transaction management. Spring reference is the best place for all your questions on this.
The most important concepts to grasp with regard to the Spring Framework's declarative transaction support are that this support is enabled via AOP proxies, and that the transactional advice is driven by metadata (currently XML- or annotation-based). The combination of AOP with transactional metadata yields an AOP proxy that uses a TransactionInterceptor in conjunction with an appropriate PlatformTransactionManager implementation to drive transactions around method invocations.
and on <aop:aspectj-autoproxy proxy-target-class="true"/>
The proxy-target-class attribute on the
element controls what type of transactional proxies are created for
classes annotated with the #Transactional annotation. If
proxy-target-class attribute is set to true, class-based proxies are
created. If proxy-target-class is false or if the attribute is
omitted, standard JDK interface-based proxies are created. (See
Section 8.6, “Proxying mechanisms” for a discussion of the different
proxy types.)
As far as I know, Spring uses JDK to generate dynamic proxy for the classes that implement any inferface while use Cglib to generate dynamic proxy for the classes that do not implement any inferface. For decarative transcation, Spring uses proxy to add transaction aspect. Please take a look at the code below:
interface Demo {
void methodA();
}
public class DemoImpl implements Demo{
#Transactional
public void updateA() {}
#Transactional
public void updateB() {}
}
I think updateA can work well with transaction. But how about updateB method? Does the #Transactional work for it?
Maybe my understanding is not correct. It's great if the related Spring source code is provided to explain how Spring use JDK/cglib to proxy the class and interface. Thanks
I have the config in the xml:
<tx:annotation-driven transaction-manager="transactionManager" />
JDK dynamic proxy
In this case your bean is wrapped with a proxy implementing Demo interface. From that moment you can only use that interface. Trying to inject or fetch bean of DemoImpl type will result in dreadful Abstract DAO pattern and Spring's "Proxy cannot be cast to ..." problem!
This kind of answers your question - you can only access updateA() and this is the only transactional method. Annotation around updateB() is ignored.
However if you call updateB() from updateA() it will be transactional because it will bind to a transaction started by updateA() (with default transaction propagation).
CGLIB proxy
In this case the interface is ignored. cglib will create a subclass of DemoImpl (obviously also implementing Demo interface) and apply transaction behaviour on both update*() methods. Now if you inject bean of type DemoImpl (interface is not needed in this case at all and Impl suffix is ugly) you can safely and transactionally call both methods.
See my article: Spring pitfalls: proxying and Spring AOP riddle for greater details.
I came across an example of #Autowired:
public class EmpManager {
#Autowired
private EmpDao empDao;
}
I was curious about how the empDao get sets since there are no setter methods and it is private.
Java allows access controls on a field or method to be turned off (yes, there's a security check to pass first) via the AccessibleObject.setAccessible() method which is part of the reflection framework (both Field and Method inherit from AccessibleObject). Once the field can be discovered and written to, it's pretty trivial to do the rest of it; merely a Simple Matter Of Programming.
Java allows you to interact with private members of a class via reflection.
Check out ReflectionTestUtils, which is very handy for writing unit tests.
No need for any setter, you just have to declare the EmpDao class with the annotation #component in order that Spring identifies it as part of the components which are contained in the ApplicationContext ...
You have 2 solutions:
To manually declare your beans in the XML file applicationContext :
<bean class="package.EmpDao" />
To use automatic detection by seeting these lines in your context file:
<context:component-scan base-package="package" />
<context:annotation-config />
AND to use the spring annotation to declare the classes that your spring container will manage as components:
#Component
class EmpDao {...}
AND to annotate its reference by #Autowired:
#Component (or #Controller, or #Service...)
class myClass {
// tells the application context to inject an instance of EmpDao here
#Autowired
EmpDao empDao;
public void useMyDao()
{
empDao.method();
}
...
}
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
Spring knows the existence of the beans EmpDao and MyClass and will instantiate automatically an instance of EmpDao in MyClass.
Spring uses the CGLib API to provide autowired dependency injection.
References
Usage of CGLib forum comment by Rod Johnson
3.3.1. Injecting dependencies
Pro Spring - Analyzing Spring Dependencies
Further Reading
Introduction to the Spring Framework by Rod Johnson