Topic 5:- 5 concept of AOP and 5 types of Advices in AOP

Understanding AOP (Aspect-Oriented Programming) in Spring

Github project link (Xml based) – https://github.com/kuldeep101990/SpringAOPXml

Github project link (Annotation based) – https://github.com/kuldeep101990/SpringAOPAnnotation

1- Aspect

An Aspect is a class that defines common behaviors (advices) to be applied at specific points (join points) in your application. It can be configured via XML or using Spring’s AspectJ integration.

2- Join Point

A Join Point is a specific point in the execution of your application where an aspect can be applied. Spring primarily supports method execution as join points.

Example:

public class UserServiceImpl implements UserService {
    public void addUser(User user) {
        // Implementation code to add a user
    }
}
// Here, the execution of addUser() is a join point where an aspect can be applied.

3- Advice

Advice is the action taken at a join point. It can run before, after, or around method execution.

Example of Before Advice:

public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))") // Match any method in service package
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before " + joinPoint.getSignature().getName() + " method is called");
    }
}
// logBefore() logs a message before the matched method executes.

4- Target Object

The Target Object is the object being advised by aspects. In Spring, this is usually a proxy object.

Example:

@Configuration
@EnableAspectJAutoProxy // Enable AspectJ proxying
public class AppConfig {
    @Bean
    public LoggingAspect loggingAspect() {
        return new LoggingAspect();
    }
    @Bean
    public UserService userService() {
        return new UserServiceImpl(); // Target object
    }
}

5- Weaving

Weaving is the process of linking aspects with target objects to create advised proxy objects. This occurs at runtime in Spring.

Example of Weaving:

// Same AppConfig as before enables weaving of aspects with the UserService

Types of Advice

  1. Before Advice:
   @Before("execution(* com.example.UserService.addUser(..))")
   public void beforeAddUserAdvice() {
       System.out.println("Before adding a user...");
   }
  1. After Returning Advice:
   @AfterReturning("execution(* com.example.UserService.getUser(..))")
   public void afterGetUserAdvice() {
       System.out.println("After getting a user...");
   }
  1. After Throwing Advice:
   @AfterThrowing(value="execution(* com.example.UserService.deleteUser(..))", throwing="ex")
   public void afterDeleteUserAdvice(Throwable ex) {
       System.out.println("Exception during delete: " + ex.getMessage());
   }
  1. After Advice (Finally):
   @After("execution(* com.example.UserService.*(..))")
   public void afterUserServiceAdvice() {
       System.out.println("After UserService method call...");
   }
  1. Around Advice:
   @Around("execution(* com.example.UserService.getAllUsers(..))")
   public Object aroundGetAllUsersAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
       System.out.println("Before getting all users...");
       Object result = joinPoint.proceed(); // Proceed with the original method
       System.out.println("After getting all users...");
       return result; // Return the result
   }

Integrating AOP with Logging

Without IoC

public class SimpleSpellChecker implements SpellChecker {
    public void checkSpelling() {
        System.out.println("Inside checkSpelling method.");
        Logger.getLogger(SimpleSpellChecker.class.getName()).info("Starting checkSpelling...");
    }
}
public class TextEditor {
    private SpellChecker spellChecker;
    public TextEditor() {
        spellChecker = new SimpleSpellChecker(); // Manual instantiation
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
        Logger.getLogger(TextEditor.class.getName()).info("Finished spellCheck...");
    }
}

With IoC

@Component
public class SimpleSpellChecker implements SpellChecker {
    @Override
    public void checkSpelling() {
        System.out.println("Inside checkSpelling method.");
    }
}
@Component
public class TextEditor {
    private SpellChecker spellChecker;
    @Autowired // Spring automatically injects the dependency
    public TextEditor(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Starting method execution: " + joinPoint.getSignature().getName());
    }
    @After("execution(* com.example.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("Finishing method execution: " + joinPoint.getSignature().getName());
    }
}

Conclusion

Using AOP in Spring allows for modular and maintainable code by separating cross-cutting concerns like logging. This makes it easier to manage and apply behaviors across various components without changing their source code.

Other AOP Features

1- Caching

Use AOP to cache the results of expensive method calls.

@Aspect
@Component
public class CachingAspect {
    private Map<String, Object> cache = new HashMap<>();
    @Around("execution(* com.example.service.*.*(..))")
    public Object cacheResult(ProceedingJoinPoint joinPoint) throws Throwable {
        String key = joinPoint.getSignature().toString();
        if (cache.containsKey(key)) {
            return cache.get(key); // Return cached result
        }
        Object result = joinPoint.proceed(); // Proceed with method execution
        cache.put(key, result); // Cache the result
        return result;
    }
}

2- Transactions

Manage transactions without cluttering business logic.

@Aspect
@Component
public class TransactionAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Transaction started.");
        try {
            Object result = joinPoint.proceed(); // Proceed with method execution
            System.out.println("Transaction committed.");
            return result;
        } catch (Exception e) {
            System.out.println("Transaction rolled back.");
            throw e; // Handle exception
        }
    }
}

3- Exception Handling

Centralize exception handling logic.

@Aspect
@Component
public class ExceptionHandlingAspect {
    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
    public void handleException(Throwable ex) {
        System.out.println("Exception occurred: " + ex.getMessage());
        // Additional logging or handling logic here
    }
}

4- Performance Monitoring

Measure method execution times.

@Aspect
@Component
public class PerformanceMonitoringAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // Proceed with method execution
        long duration = System.currentTimeMillis() - start;
        System.out.println("Execution time: " + duration + " ms");
        return result;
    }
}

5- Security

Apply security checks across methods.

@Aspect
@Component
public class SecurityAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void checkSecurity() {
        // Implement security checks here
        System.out.println("Security check passed.");
    }
}

6- Validation

Ensure input data validity.

@Aspect
@Component
public class ValidationAspect {
    @Before("execution(* com.example.service.*.*(..)) && args(input)")
    public void validateInput(String input) {
        if (input == null || input.isEmpty()) {
            throw new IllegalArgumentException("Input cannot be null or empty.");
        }
    }
}

These code snippets demonstrate how to implement common AOP features using Spring, promoting better code organization and separation of concerns.


5 comments

  1. Hi there, just became alert to your blog through Google,and found that it is truly informative. I am gonna watch outfor brussels. I’ll be grateful if you continue this in future.Lots of people will be benefited from your writing.Cheers!

  2. Thanks for your fascinating article. One other problem is that mesothelioma is generally the result of the inhalation of material from asbestos fiber, which is a dangerous material. Its commonly viewed among staff in the engineering industry who definitely have long contact with asbestos. It is caused by residing in asbestos insulated buildings for an extended time of time, Genetic makeup plays a huge role, and some persons are more vulnerable on the risk in comparison with others.

  3. Hiya, I’m really glad I’ve found this information. Nowadays bloggers publish just about gossips and net and this is actually annoying. A good site with exciting content, that’s what I need. Thanks for keeping this web site, I’ll be visiting it. Do you do newsletters? Cant find it.

  4. I am very happy to read this. This is the type of manual that needs to be given and not the random misinformation that is at the other blogs. Appreciate your sharing this best doc.

  5. I was suggested this blog by my cousin. I am not sure whether or not this submit is written through him as no one else realize such distinctive approximately my trouble. You’re incredible! Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *