1

I'm learning the bean AOP with Annotation and xml config but Spring does not create the beans.

Interface

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation; public interface Artist { void perform(); } 

Guitar Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation; import org.springframework.stereotype.Component; @Component("grammyGuitarist") public class GrammyGuitarist implements Artist{ @Override public void perform() { System.out.println("Start to play guitar"); } public void playGuitar(String brand) { System.out.println("Get Guitar "+brand); } public void rest() { System.out.println("zzZZ!!!!"); } } 

Documentarist

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component(value="documentaries") public class Documentarist { private GrammyGuitarist guitarist; public void executed() { guitarist.playGuitar("LakeWood"); guitarist.perform(); guitarist.rest(); } @Autowired public void setGuitarist(GrammyGuitarist guitarist) { this.guitarist = guitarist; } } 

Advice Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component("annotatedAdvice") @Aspect public class AnnotatedAdvice { @Pointcut("execution(* rest*(..)) && args(brand)") public void restExecution(String brand) { } @Pointcut("bean(grammyGuitarist)") public void isGrammyGuitarist() { } @Before("restExecution(brand) && isGrammyGuitarist") public void simpleBeforeAdvice(JoinPoint joinPoint , String brand) { System.out.println("Before Advice processing"); System.out.println("Playing guitar :" + brand); System.out.println("Executing :"+ joinPoint.getSignature().getDeclaringTypeName() +" "+joinPoint.getSignature().getName()); } } 

Demo Class

package com.spring.studying.SpringAop.FrameworkService.AspectJAnnotation; import org.springframework.context.support.GenericXmlApplicationContext; import java.util.Arrays; public class AspectJAnnotationDemo { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("aop-aspectj-annotation-style.xml"); ctx.refresh(); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); Documentarist documentarist = ctx.getBean("documentaries",Documentarist.class); documentarist.executed(); } } 

My Xml Config File

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <context:annotation-config/> <context:component-scan base-package="com.spring.studying.SpringAop"/> <aop:aspectj-autoproxy/> </beans> 

None of my beans were created just 6 default beans from spring.

I have try to create bean with tag and it worked fine . Just don't know why my code did not work with the annotation.

4
  • Stop using the outdated xml configuration in spring. Use the java configuration instead Commented Aug 7, 2022 at 11:38
  • i tried both of them for learning :D Commented Aug 7, 2022 at 11:39
  • Why you learn outdated things? Commented Aug 7, 2022 at 11:42
  • I need to upgrade an old project Commented Aug 7, 2022 at 18:56

1 Answer 1

1

restExecution @Pointcut is wrong, because rest method of GrammyGuitarist doesn't take any arguments. playGuitar method takes brand argument, so you need to change your pointcut a bit:

@Component("annotatedAdvice") @Aspect public class AnnotatedAdvice { @Pointcut("execution(* play*(..)) && args(brand)") public void playExecution(String brand) { } @Pointcut("bean(grammyGuitarist)") public void isGrammyGuitarist() { } @Before("playExecution(brand) && isGrammyGuitarist()") public void simpleBeforeAdvice(JoinPoint joinPoint, String brand) { System.out.println("Before Advice processing"); System.out.println("Playing guitar :" + brand); System.out.println("Executing :" + joinPoint.getSignature().getDeclaringTypeName() + " " + joinPoint.getSignature().getName()); } } 

When you do this, aspects will indeed be created, but you will start getting exceptions:

Bean named 'grammyGuitarist' is expected to be of type 'com.example.demo.aspect.GrammyGuitarist' but was actually of type 'jdk.proxy2.$Proxy14' 

This is because GrammyGuitarist implements an interface, and in this case Spring AOP uses JDK dynamic proxies

The simplest solution would be to force the use of a CGLIB proxy. To do this, you need to add an annotation above the aspect:

@EnableAspectJAutoProxy(proxyTargetClass = true) 

After that, the program will give the expected result:

annotatedAdvice documentaries grammyGuitarist org.springframework.aop.config.internalAutoProxyCreator Before Advice processing Playing guitar :LakeWood Executing :com.example.demo.aspect.GrammyGuitarist playGuitar Get Guitar LakeWood Start to play guitar zzZZ!!!! 

In Spring Boot, CGLIB enforcement is enabled by default. Check this question for better understanding

Sign up to request clarification or add additional context in comments.

1 Comment

I think the cglib can work with my GrammyGuitarist class. The JDK will create an instance that implement the Singer interface but my Guitarist class has more method

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.