m. AOP - kimxavi/spring_tutorial GitHub Wiki

์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ค‘์š”ํ•œ ์š”์†Œ ์ค‘์— ํ•˜๋‚˜๊ฐ€ Aspect oriented programming (AOP) ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ด๋‹ค. AOP๋Š” ํ”„๋กœ๊ทธ๋žจ ๋กœ์ง์„ ๊ด€์‹ฌ์‚ฌ์— ๋”ฐ๋ผ ๋ณ„๊ฐœ์˜ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ ๊ณณ์— ๊ฑธ์ณ ์žˆ๋Š” ๊ธฐ๋Šฅ์€ cross-cutting concerns ์ด๋ผ ๋ถˆ๋ฆฌ์–ด์ง„๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ฒƒ๋“ค์˜ cross-cutting concerns์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์œผ๋กœ๋ถ€ํ„ฐ ๊ฐœ๋…์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด์ง„๋‹ค. ๋กœ๊น…, ํŠธ๋žœ์žญ์…˜, ์‹œํ๋ฆฌํ‹ฐ, ์บ์‹œ, ๊ทธ์™ธ ๋“ฑ๋“ฑ ์ธก๋ฉด์˜ ๋งŽ์€ ์˜ˆ๊ฐ€ ์žˆ๋‹ค. OOP์—์„œ ๋ชจ๋“ˆํ™”์˜ ํ•ต์‹ฌ ๋‹จ์œ„๋Š” ํด๋ž˜์Šค์ด๋‹ค. ๊ทธ์— ๋ฐ˜ํ•ด, AOP์˜ ๋ชจ๋“ˆํ™” ๋‹จ์œ„๋Š” aspect์ด๋‹ค. Dependency Injection์€ ๊ฐ์ฒด๋ฅผ ์„œ๋กœ๋กœ ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ์‹œ์ผœ์ฃผ๋Š” ๊ฑธ ๋•๋Š”๋‹ค ๊ทธ๋ฆฌ๊ณ  AOP๋Š” ๊ทธ ๊ฐ์ฒด๋“ค์ด ์˜ํ–ฅ์„ ๋ผ์น˜๋Š” ๊ฒƒ์œผ๋กœ ๋ถ€ํ„ฐ cross-cutting concerns ์„ ๋ถ„๋ฆฌ์‹œ์ผœ์ค€๋‹ค. ์Šคํ”„๋ง AOP ๋ชจ๋“ˆ์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ interceptํ•˜๋Š” intercepter๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ „/ํ›„ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•  ์ˆ˜์žˆ๋‹ค.

AOP Terminologies

  • Aspect : cross-cutting๋˜๋Š” ์š”๊ตฌ๋ฅผ ์ œ๊ณตํ•˜๋Š” API ๋“ค์˜ ์ง‘ํ•ฉ ๋ชจ๋“ˆ. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ๊น… ๋ชจ๋“ˆ์€ ๋กœ๊น…์„ ์œ„ํ•œ AOP์˜ Aspect๋ฅผ ํ˜ธ์ถœ ํ•  ๊ฒƒ์ด๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ•„์š”์— ๋”ฐ๋ผ aspect์˜ ์ˆ˜์—๋Š” ์ œํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.
  • Join point : ์ด๊ฒƒ์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ AOP aspect ๋ฅผ ํ”Œ๋Ÿฌ๊ธด ํ•  ์‹œ์ ์„ ํ‘œํ˜„ํ•œ๋‹ค. ์Šคํ”„๋ง AOP ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ž‘ํ•˜๋Š” ์‹ค์ œ ์žฅ์†Œ์ด๋‹ค.
  • Advice : ์ด๋Š” ์‹ค์ œ ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ „/ํ›„์— ๊ฐ€์ ธ์ง€๋Š” ์‹ค์ œ ์ž‘์—…์ด๋‹ค. ์ด ์‹ค์ œ ์ฝ”๋“œ ๋ถ€๋ถ„์€ ์Šคํ”„๋ง AOP ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ค‘์— ํ˜ธ์ถœ๋œ๋‹ค.
  • Pointcut : advice ๊ฐ€ ์‹คํ–‰๋˜์•ผํ•˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ Join point ์ง‘ํ•ฉ์ด๋‹ค. expressions ์ด๋‚˜ patterns ์„ ์‚ฌ์šฉํ•ด์„œ ๋ช…์‹œํ•ด์ค€๋‹ค.
  • Introduction : Introduction๋Š” ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๋‚˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํด๋ž˜์Šค์— ๋”ํ•ด์ฃผ๋Š” ๊ฒƒ์„ ํ—ˆ๋ฝํ•œ๋‹ค.
  • Target object : ํ•˜๋‚˜ ์ด์ƒ์˜ aspect๋“ค์— ์˜ํ•ด Advice ๊ฐ€ ์ž‘๋™ํ•  ๊ฐ์ฒด. ์ด ๊ฐ์ฒด๋Š” ํ•ญ์ƒ proxied object ์ด๋‹ค. ๋˜ํ•œ, advised object๋กœ์„œ ์–ธ๊ธ‰๋œ๋‹ค.
  • Weaving : Weaving์€ ๋‹ค๋ฅธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํƒ€์ž…๋“ค๊ณผ aspect ๋“ค์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๊ณผ์ • ๋˜๋Š” advised object๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐ์ฒด์ด๋‹ค. compile time, load time, ๋˜๋Š” runtime ์— ๋งˆ๋ฌด๋ฆฌ๋œ๋‹ค.

Types of Advice

  • before : ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ „์— advice๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • after : ์ด ๊ฒƒ์˜ ๊ฒฐ๊ณผ์— ์ƒ๊ด€ ์—†์ด ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ํ›„์— advice๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • after-returning : ๋ฉ”์†Œ๋“œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰ ๋์œผ๋ฉด ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ํ›„์— advice๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • after-throwing : ๋ฉ”์†Œ๋“œ์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒ ํ–ˆ์œผ๋ฉด ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ํ›„์— advice๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  • around : ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ ์ „ํ›„์— advice๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

Custom Aspects Implementation

XML Schema based

์ด ์„น์…˜์—์„  aop ๋„ค์ž„์ŠคํŽ˜์ด์Šค ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„ํ•œ๋‹ค. spring-aop๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด importํ•ด์ค˜์•ผ ํ•œ๋‹ค.

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <!-- bean definition & AOP specific configuration -->

</beans>
  • Declaring an aspect : aop:aspect ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ aspect๋Š” ์„ ์–ธ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  bean์€ ref๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐธ์กฐ๋œ๋‹ค.
<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   ...
   </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
...
</bean>
  • Declaring a pointcut : ํฌ์ธํŠธ ์ปท์€ ๋‹ค๋ฅธ advice๋“ค๋กœ ์‹คํ–‰๋˜๋Š” ๊ด€์‹ฌ์˜ ์กฐ์ธ ํฌ์ธํŠธ (์ฆ‰, ๋ฐฉ๋ฒ•)๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค. XML ๊ธฐ๋ฐ˜ ์„ค์ • ํŒŒ์ผ๋กœ ์ž‘๋™ํ•  ๋•Œ, pointcut ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์˜ํ•œ๋‹ค.
<aop:config>
   <aop:aspect id="myAspect" ref="aBean">

   <aop:pointcut id="businessService"
      expression="execution(* com.xyz.myapp.service.*.*(..))"/>
   ...
   </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
...
</bean>

์•„๋ž˜์™€ ๊ฐ™์ด Student์˜ getName() ๋ฉ”์†Œ๋“œ ์‹คํ–‰์— ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">

   <aop:pointcut id="businessService"
      expression="execution(* com.tutorialspoint.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
...
</bean>
  • Declaring advices : ๋‹ค์„ฏ๊ฐœ์˜ advice๋“ค์„ aop:aspect ๋‚ด๋ถ€์— aop:{ADVICE NAME}๋ฅผ ์จ์„œ ์„ ์–ธํ–ˆ๋‹ค.
<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
      <aop:pointcut id="businessService"
         expression="execution(* com.xyz.myapp.service.*.*(..))"/>

      <!-- a before advice definition -->
      <aop:before pointcut-ref="businessService" 
         method="doRequiredTask"/>

      <!-- an after advice definition -->
      <aop:after pointcut-ref="businessService" 
         method="doRequiredTask"/>

      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning pointcut-ref="businessService"
         returning="retVal"
         method="doRequiredTask"/>

      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing pointcut-ref="businessService"
         throwing="ex"
         method="doRequiredTask"/>

      <!-- an around advice definition -->
      <aop:around pointcut-ref="businessService" 
         method="doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
...
</bean>

doRequiredTask ๋กœ ๋™์ผํ•˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๊ณ  ๋‹ค๋ฅธ advice๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ๋ฉ”์†Œ๋“œ๋“ค์€ aspect ๋ชจ๋“ˆ์˜ ํ•œ ๋ถ€๋ถ„์œผ๋กœ ์ •์˜๋  ๊ฒƒ์ด๋‹ค.

  • ์˜ˆ์‹œ

Logging.java

package com.tutorialspoint;

public class Logging {

   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
    * This is the method which I would like to execute
    * if there is an exception raised.
    */
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }
   
}

Student.java

package com.tutorialspoint;

public class Student {
   private Integer age;
   private String name;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
	  System.out.println("Age : " + age );
      return age;
   }

   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      System.out.println("Name : " + name );
      return name;
   }
   
   public void printThrowException(){
	   System.out.println("Exception raised");
       throw new IllegalArgumentException();
   }
}

MainApp.java

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      Student student = (Student) context.getBean("student");

      student.getName();
      student.getAge();
      
      student.printThrowException();
   }
}

Beans.xml

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <aop:config>
      <aop:aspect id="log" ref="logging">
         <aop:pointcut id="selectAll" 
         expression="execution(* com.tutorialspoint.*.*(..))"/>
         <aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
         <aop:after pointcut-ref="selectAll" method="afterAdvice"/>
         <aop:after-returning pointcut-ref="selectAll" 
                              returning="retVal"
                              method="afterReturningAdvice"/>
         <aop:after-throwing pointcut-ref="selectAll" 
                             throwing="ex"
                             method="AfterThrowingAdvice"/>
      </aop:aspect>
   </aop:config>

   <!-- Definition for student bean -->
   <bean id="student" class="com.tutorialspoint.Student">
      <property name="name"  value="Zara" />
      <property name="age"  value="11"/>      
   </bean>

   <!-- Definition for logging aspect -->
   <bean id="logging" class="com.tutorialspoint.Logging"/> 
      
</beans>

PRINT

Going to setup student profile.
Name : Zara
Student profile has been setup.
Returning:Zara
Going to setup student profile.
Age : 11
Student profile has been setup.
Returning:11
Going to setup student profile.
Exception raised
Student profile has been setup.
There has been an exception: java.lang.IllegalArgumentException
.....
other exception content

@AspectJ Based AOP with Spring

@AspectJ ๋Š” Java 5 ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ํ•จ๊ป˜ ์ž๋ฐ” ํด๋ž˜์Šค์˜ ์ผ๋ฐ˜์ ์ธ aspect ์„ ์–ธ ๋ฐฉ๋ฒ•์ด๋‹ค. @AspectJ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด XML ์„ค์ • ํŒŒ์ผ์— ์š”์†Œ๋ฅผ ๋„ฃ์Œ์œผ๋กœ์จ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

<aop:aspectj-autoproxy/>
  • Declaring an aspect : Aspects ํด๋ž˜์Šค๋“ค์€ @Aspect๊ฐ€ ์–ด๋…ธํ…Œ์ดํŠธ ๋์„ ๋ฟ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋“ค๊ณผ ๋˜‘๊ฐ™๋‹ค.
package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

XML ์„ค์ • ํŒŒ์ผ์—”

<bean id="myAspect" class="org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>
  • Declaring a pointcut : @AspectJ ์ผ ๋•Œ ๋‘ ๊ฐ€์ง€ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰œ๋‹ค.
    • pointcut expression ๋Š” ์ •ํ™•ํžˆ ๊ด€์‹ฌ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
    • pointcut signature ๋Š” ์ด๋ฆ„๊ณผ ๋ช‡๋ช‡์˜ ์ธ์ž๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์‹ค์ œ ๋ชธ์ฒด๋Š” ์ƒ๊ด€ ์—†๋‹ค. ์‹ค์ œ๋กœ ๋น„์–ด์žˆ๋‹ค.
import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature
import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.tutorialspoint.Student.getName(..))") 
private void getname() {}
  • Declaring advices : ๋‹ค์„ฏ๊ฐœ์˜ advice๋ฅผ @{ADVICE-NAME}๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.
@Before("businessService()")
public void doBeforeTask(){
 ...
}

@After("businessService()")
public void doAfterTask(){
 ...
}

@AfterReturning(pointcut = "businessService()", returning="retVal")
public void doAfterReturnningTask(Object retVal){
  // you can intercept retVal here.
  ...
}

@AfterThrowing(pointcut = "businessService()", throwing="ex")
public void doAfterThrowingTask(Exception ex){
  // you can intercept thrown exception here.
  ...
}

@Around("businessService()")
public void doAroundTask(){
 ...
}

์ธ๋ผ์ธ ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
 ...
}
  • ์˜ˆ์‹œ Logging.java
package com.tutorialspoint;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;

@Aspect
public class Logging {

   /** Following is the definition for a pointcut to select
    *  all the methods available. So advice will be called
    *  for all the methods.
    */
   @Pointcut("execution(* com.tutorialspoint.*.*(..))")
   private void selectAll(){}

   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
   @Before("selectAll()")
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   @After("selectAll()")
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   @AfterReturning(pointcut = "selectAll()", returning="retVal")
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
    * This is the method which I would like to execute
    * if there is an exception raised by any method.
    */
   @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }
   
}

Student.java

package com.tutorialspoint;

public class Student {
   private Integer age;
   private String name;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
	  System.out.println("Age : " + age );
      return age;
   }

   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      System.out.println("Name : " + name );
      return name;
   }
   public void printThrowException(){
      System.out.println("Exception raised");
      throw new IllegalArgumentException();
   }
}

MainApp.java

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      Student student = (Student) context.getBean("student");

      student.getName();
      student.getAge();
      
      student.printThrowException();
   }
}

Beans.xml

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <aop:aspectj-autoproxy/>

   <!-- Definition for student bean -->
   <bean id="student" class="com.tutorialspoint.Student">
      <property name="name"  value="Zara" />
      <property name="age"  value="11"/>      
   </bean>

   <!-- Definition for logging aspect -->
   <bean id="logging" class="com.tutorialspoint.Logging"/> 
      
</beans>

PRINT

Going to setup student profile.
Name : Zara
Student profile has been setup.
Returning:Zara
Going to setup student profile.
Age : 11
Student profile has been setup.
Returning:11
Going to setup student profile.
Exception raised
Student profile has been setup.
There has been an exception: java.lang.IllegalArgumentException
.....
other exception content
โš ๏ธ **GitHub.com Fallback** โš ๏ธ