Spring-AOP

Ai_gWMr6EMaBE5DiYPZUox55qOsok8yDrJ8xm_WHOEmF

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

Instead of maintaining business logic and services logic together, develop services and business logic separately. Inject those services in to Business class using AOP

Maintaining Service logic separately from Business logic 

Services are like Transaction Services, Security, Mailing, JMS Services

Aspect is nothing but a Service
Advice is nothing but a ServiceProvider. By using Advice you can provide ASPECT
PointCut is nothing but a point or condition to execute aspects for your business methods.
Adviser is nothing but pointcut with advice combination
Proxy is a waiver (proxy object will be generated by combining service and business code)
target is nothing but businees object

We can implement in 3 approaches
Programatic approach
Declarative approach
Annotation approach

Programatic approach

org.springframework.aop.MethodBeforeAdvice;
org.springframework.aop.AfterReturningAdvice;
org.springframework.aop.ThrowsAdvice;
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor;


Programatic approach:

public class LoggingBefore  implements MethodBeforeAdvice{

    Logger log = LoggerFactory.getLogger(LoggingBefore.class);

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        log.debug("before calling enrollStudent method");
        log.debug(method.getName());
        log.debug(objects.toString());
    }
}

Client Class:

//create target
BankServiceImpl bsi = new BankServiceImpl();
//create advice
LogBeforeService lbs = new LogBeforeService()

//generating proxy by combining target + advice
ProxyFactoryBean pfb = new ProxyFactoryBean();
pfb.setTarget(bsi);
pfb.addAdvice(loggingBefore);

//get generated proxy object
BankServiceImpl bsi =(BankServiceImpl)pfb.getObject();


Declarative approach
   

<!--Target -->
   <bean id="stdImpl" class="com.springapp.mvc.service.EnrollStudentServiceImpl"/>

    <!-- advice -->
    <bean id="logBef" class="com.springapp.mvc.aop.LoggingBefore"/>
   
    <!-- proxyBean-->
    <bean id="proxyStudentImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="stdImpl"/>
        <property name="interceptorNames">
            <list>
                <value>logBef</value>
            </list>
        </property>
    </bean>

Pointcuts : If you want to specify where exactly service need to be executed then we can use pointcut
StaticMethodMatcherPointcut
NameMatchMatcherPointcut

public class EnrollPointCut extends StaticMethodMatcherPointcut {
    @Override
    public boolean matches(Method method, Class<?> aClass) {
        if(method.getName().equals("enrollStudent")){
            return true;
        }
        return false;
    }
}

Advicer:
DefaultPointcutAdvicer
RegexpMethodPointcutAdvicer   

 <!--Target -->
   <bean id="stdImpl" class="com.springapp.mvc.service.EnrollStudentServiceImpl"/>

    <!-- advice -->
    <bean id="logBef" class="com.springapp.mvc.aop.LoggingBefore"/>

    <!-- pointCut -->
    <bean id="enrollPointCut" class ="com.springapp.mvc.aop.EnrollPointCut"/>
    <!-- Advisor -->
    <bean id="dpa" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="logBef"/>
        <property name="pointcut" ref="enrollPointCut"/>
    </bean>

    <!-- proxyBean-->
    <bean id="proxyStudentImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="stdImpl"/>
        <property name="interceptorNames">
            <list>
                <value>dpa</value>
            </list>
        </property>
    </bean>