So, i have started learning spring boot and i came across AOP.
I made myself an aspect which looks something like this
@Aspect
public class Logging {
@Pointcut("execution(* com.tilak.*.*(..))")
private void selectAll(){}
@Before("selectAll()")
private void beforeAdvice(){
System.out.println("Going to set up student profile");
}
@After("selectAll()")
private void afterAdvice(){
System.out.println("student profile has been set.");
}
@AfterReturning(pointcut = "selectAll()" , returning = "retVal")
private void afterReturningAdvice(Object retVal){
System.out.println("Returning: "+ retVal.toString());
}
@AfterThrowing(pointcut = "selectAll()" , throwing = "ex")
private void afterThrowingAdvice(IllegalArgumentException ex){
System.out.println("There has been an exception: " + ex.toString());
}
}
I have one more class Student which looks like this
@Component
public class Student {
private Integer age;
private String game;
public Integer getAge() {
System.out.println("Age : " + age );
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGame() {
System.out.println("Name : " + game);
return game;
}
public void setGame(String game) {
this.game = game;
}
public void printThrowException(){
System.out.println("Exception raised");
throw new IllegalArgumentException();
}
}
Main Class looks like this
@SpringBootApplication
public class MainApp {
public static void main(String... z) {
SpringApplication.run(MainApp.class, z);
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanMe.class);
Student student = (Student) applicationContext.getBean("student");
student.getAge();
student.getGame();
student.printThrowException();
}
}
Bean class looks like this
@Configuration
public class BeanMe {
@Bean(name = "student")
public Student studentBean(){
Student student = new Student();
student.setAge(24);
student.setGame("Tilak raj");
return student;
}
@Bean("logging")
public Logging loggingBean(){
return new Logging();
}
}
Pom file :
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springbootexample</groupId>
<artifactId>firstspringboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<game>firstspringboot</game>
<description>Practise project for spring boot
</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-data-jpa</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My output:
Age : 24 Name : Tilak raj Exception raised Exception in thread "main" java.lang.IllegalArgumentException at com.tilak.aop.Student.printThrowException(Student.java:33) at com.tilak.aop.MainApp.main(MainApp.java:24)
I think i have included every dependency needed to make this run but i am not getting the expected output.
The Advices should run but they are not. What am i missing here?
Update:
Your code in the main
method is doing the wrong things. The SpringApplication.run(MainApp.class, z);
already returns an ApplicationContext
you are constructing it again and only with a part of your configuration. The missing part is the fact that this doesn't have aspectj enabled.
However as you are re-loading an already loaded context don't do that, use Spring Boot in a proper way.
@SpringBootApplication
public class MainApp {
public static void main(String... z) {
ApplicationContext ctx = SpringApplication.run(MainApp.class, z);
Student student = ctx.getBean("student", Student.class);
student.getAge();
student.getGame();
student.printThrowException();
}
}
This will load the application, retrieve the bean and call the methods.
Next to that your pointcut expression is also wrong. execution(* com.tilak.*.*(..))
means the exception of all methods for classes in the com.tilak
package. As your classes are in the com.tilak.aop
package that doesn't match.
Use either execution(* com.tilak..*.*(..))` or
execution(* com.tilak.aop..(..))either will work. The first includes sub packages due to the
..` the other one uses the full package.
However doing so will result in another issue, the aspect will create apply to itself as well (you will notice this when starting the application). So you want to limit it either to the Student
class or exclude classes annotated with @Aspect
.
To test you can use execution(* com.tilak.aop.Student.*(..))
as the pointcut as that will match only the Student
class and not the aspect.