I have many aspect class in com.aop.aspect package. What I want to do is to work all class except for one class named for com.aop.dao.MyDemoLoggingAspect
When I run the app, there is an error appeared on the console.
java.lang.IllegalArgumentException: warning no match for this type name: com.aop.dao.MyDemoLoggingAspect [Xlint:invalidAbsoluteTypeName]
Here is my aspect class
#Aspect
public class LuvAopExpressionsOrder {
#Pointcut("execution(* com.aop.dao.*.*(..))")
public void forDaoPackage() {}
// create pointcut for getter methods
#Pointcut("execution(* com.aop.dao.*.get*(..))")
public void getter() {}
// create pointcut for setter methods
#Pointcut("execution(* com.aop.dao.*.set*(..))")
public void setter() {}
// create pointcut for setter methods
#Pointcut("!execution(* com.aop.dao.MyDemoLoggingAspect.*(..))")
public void excludeMyDemoLoggingAspect() {}
// create pointcut: include package ... exclude getter/setter and MyDemoLoggingAspect
#Pointcut("forDaoPackage() && !(getter() || setter()) && excludeMyDemoLoggingAspect() ")
public void forDaoPackageNoGetterSetter() {}
}
If you use Spring AOP you don't need to be afraid that one aspect will intercept methods from another because Spring does not support that, as is documented in chapter 5.4.2. Declaring an Aspect. Scroll down a bit and look for this info box:
Advising aspects with other aspects?
In Spring AOP, aspects themselves cannot be the targets of advice from other aspects. The #Aspect annotation on a class marks it as an aspect and, hence, excludes it from auto-proxying.
So basically your issue is a non-issue.
If however you use AspectJ via LTW you are subject to no such limitations and thus have to be careful to exclude other aspects which would normally be intercepted due to matching pointcuts. I recommend to put aspects in packages which are easy to exclude, otherwise you have to do it class name by class name. Use pointcuts like these, depending on your situation:
!within(com.aop.dao.MyDemoLoggingAspect)
!within(com.acme.aop..*)
!within(com.acme..*Aspect)
Related
I am trying to execute some code after one protected method inside abstract class gets called. It looks something like this.
abstract class SomeAbstractClass : ServiceOne, ServiceTwo {
protected fun doSomething(p1: String, p2: Int): SomeEntity {
// some business logic
return SomeEntity()
}
}
I want to create annotation class like the one below and annotate method (above) with it and I want it to execute after class method returns value. I tried this and many other variations but nothing worked for me.
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
annotation class EntityCreated {
#Aspect
#Component
class EntityAspect {
#AfterReturning("#annotation(EntityCreated)")
fun afterSuccessfulCreate(jp: JoinPoint) {
// Created, execute something here
}
}
}
While protected methods are off limits for JDK proxies when proxying interfaces, the CGLIB proxies used by Spring to extend classes can intercept protected methods. But in order to proxy a Kotlin class, you have to open it, so it is not final and can be proxied.
Please note, however, that if you override a protected method in Java, that overridden method will not "inherit" the super method's annotations. This is a Java limitation and unrelated to AOP. Annotation inheritance only works from parent to sub classes, if the annotation bears the #Inherited meta annotation. There is a way to emulate annotation inheritance using an advanced form of a technique called ITD (inter-type definition) in native AspectJ, but not in simple Spring AOP.
The exact answer to your question depends on your exact use case, your sample code is too fragmentary to answer in more detail.
I tried to use PointCut to perform some post action after ModelAndView.setViewName, but it seems that it never triggers:
#Aspect
#Component
public class TestAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Pointcut("execution(* org.springframework.web.servlet.ModelAndView.*(..))")
public void testPointCut() {
}
#After("testPointCut()")
public void afterPointCut(JoinPoint joinPoint) {
logger.debug("afterPointCut");
}
}
If I change the execution part to some class of my own, this point cut works.
So what is the correct way to add PointCut to ModelAndView?
I am not a Spring user, but what I know about Spring AOP is that you can only apply it to Spring components. The class ModelAndView is not derived from any Spring core component class or annotated by anything making it such, it is a simple POJO. As such you cannot target it by Spring AOP pointcuts. You should rather target something within the reach of Spring AOP.
The alternative would be to unpack the big gun and use full AspectJ LTW (load-time weaving) which is not limited to Spring components.
I have an annotation which will be used on extended placeholder classes. Basically, our service will have an implementation, and we will have an explicit extension which will be annotated. I am not sure what the problem is, but #within is not invoking the code whereas #target is.
Here is a sample code - https://github.com/sahil-ag/Spring-AOP-Sample
#Component
public BaseClass { public void getData() {return "";}}
#SampleAnnotation
#Component
public DerivedClass extends BaseClass {}
Here if we now use a #within(SampleAnnotation) pointcut, we will not be able to intercept the getData() when called from a derived class bean.
The #within Annotation is used when you want to define a class where the pointcuts are located in. So make sure that your within-clause looks like:
#within(#MyAnnotation *)
The '*' is used to say any class. This is the part you are missing in your example.
Another approach would be to use the #annotation pointcut:
#Annotation(#MyAnnotation)
Official documentation:
https://www.eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
I am a beginner in Spring framework. I have started learning Spring framework a couple of weeks. I did not get any proper explanation of RequiredAnnotationBeanPostProcessor. Please, someone, help me by giving some example of RequiredAnnotationBeanPostProcessor and where to use this. Thanks in advance.
RequiredAnnotationBeanPostProcessor is a not common used annotation in applications that use Spring.
The #Autowired annotation that provides both the autowiring and the requiring (by default enabled) behaviors is often preferred to.
RequiredAnnotationBeanPostProcessor is a BeanPostProcessor implementation.
The BeanPostProcessor interface defines callback methods that you can implement to provide your own (or override the container’s default) instantiation logic, dependency-resolution logic, and so forth.
In the case of RequiredAnnotationBeanPostProcessor, it enforces required JavaBean properties to have been configured.
Required bean properties are detected through a Java 5 annotation: by default, the Spring's Required annotation.
To be short, it allows to ensure that a bean that declares 'required' properties has actually been configured with values. Note that the value may be null.
For example suppose this model class :
public class Foo {
private Bar bar;
#Required
public void setBar(Bar bar) {
this.bar = bar;
}
}
If setBar() is never invoked during the initialization of the bean, a org.springframework.beans.factory.BeanInitializationException is thrown.
For example this bean configuration will trigger the exception throwing :
#Configuration
public class MyConfig {
#Bean
public Foo getFoo() {
return new Foo();
}
}
Of course if you add #Autowired to setBar() with a resolvable dependency, it will be fine :
public class Foo {
private Bar bar;
#Autowired
#Required
public void setBar(Bar bar) {
this.bar = bar;
}
}
So we could consider that a good use case for RequiredAnnotationBeanPostProcessor is a case where you don't want/cannot specify the autowiring in the class of the bean.
Note also that RequiredAnnotationBeanPostProcessor provides also an additional feature that is according to the javadoc its primary goal :
The motivation for the existence of this BeanPostProcessor is to allow
developers to annotate the setter properties of their own classes with
an arbitrary JDK 1.5 annotation to indicate that the container must
check for the configuration of a dependency injected value.
It means that you may specify another annotation that #Required to indicate the required constraint.
RequiredAnnotationBeanPostProcessor defines indeed a setRequiredAnnotationType() method that you can override to set the annotation to use.
As you can see, the use of RequiredAnnotationBeanPostProcessor is related to very specific corner cases. That's why you probably don't find many examples about it.
I try to use aspectj for checking whether the layers of the architecture are broken, e.g. the access from controller to repository without using a service between
Now this is marking every method call to a autowired annotated within de.fhb.controller.
but how can i then limit that to Repositories for example?
The package structure looks like this:
de.fhb.controller
de.fhb.service
de.fhb.entity and and so on.
my aspect looks like this
#Aspect
public class Layer {
#DeclareError("within(de.fhb.controller..*) && #annotation(org.springframework.beans.factory.annotation.Autowired) " )
private static final String typeWarning = "You try to access through many layers";
}
the repository:
#Repository
public interface BoxRepository extends JpaRepository<Box, Long>{
public List findByPrio(long prio);
}
and the controller that should be checked by aspects:
#RequestMapping("/box")
#Controller
public class BoxController {
#Autowired
private BoxRepository boxRepository; // negative example
#Autowired
private BoxService boxService;
#RequestMapping(value = "/")
public String list(Model model) {
List boxes = boxRepository.findAll(); // negativ example
model.addAttribute("boxes", boxes);
return "box/list";
}
for further look: repository at github
Your pointcut
within(de.fhb.controller..*) &&
execution(de.fhb.repository.BoxRepository *(..))
means in prose: Intercept any method in package de.fhb.controller or its sub-packages which has a return type of de.fhb.repository.BoxRepository, but in your code is no such method. So you will never see a compiler error.
;-)
Updated answer after question update:
You need to intercept calls to methods of types with a #Repository annotation:
within(de.fhb.controller..*) &&
call(* (#org.springframework.stereotype.Repository *).*(..))
But in order to do that you need to switch from Spring AOP to full-blown AspectJ with compile-time weaving, i.e. you need to use the AspectJ compiler Ajc to compile and weave your aspect. The reason is that Spring AOP does not support the call() pointcut, but this is what you need. An execution() pointcut will not help you here, but that is the only one supported by a proxy-based "AOP lite" framework like Spring AOP. You just need to weave this one aspect with AspectJ, the other aspects can still use Spring AOP. But then need to take care about AspectJ not picking up your other aspects.