深入理解spring的AOP

AOP的原理

AOP的实现有两种方式,一种是使用代理,一种是直接修改.class(即使用CGLib等类库)。

问题的引入

  
  
      
          
          
      
  
  
  
      
      
  

好神奇!这样就可以了?tx:advice是怎么实现的?如果我想要自己编写advice,那我应该要怎么做呢?

何谓Advice

如果要自己实现一个Advice,要怎么做?一个Advice包含了什么东西?怎么样的才算一个Advice?

来,先看网上一个例子:

一个需要注入的类:

package com.mkyong.customer.services;

public class CustomerService {
    private String name;
    private String url;

    public void setName(String name) {
        this.name = name;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void printName() {
        System.out.println("Customer name : " + this.name);
    }

    public void printURL() {
        System.out.println("Customer website : " + this.url);
    }

    public void printThrowException() {
        throw new IllegalArgumentException();
    }

}

before advice

package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class HijackBeforeMethod implements MethodBeforeAdvice
{
    @Override
    public void before(Method method, Object[] args, Object target)
        throws Throwable {
            System.out.println("HijackBeforeMethod : Before method hijacked!");
    }
}

如何把before advice注入到CustomerService类中:



    
        
        
    

    

    

        

        
            
                hijackBeforeMethodBean
            
        
    

customerServiceProxy就是注入了HijackBeforeMethodCustomerService吗?是的!

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService;

public class App {
    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                new String[] { "Spring-Customer.xml" });

        CustomerService cust =
                                (CustomerService) appContext.getBean("customerServiceProxy");

        System.out.println("*************************");
        cust.printName();
        System.out.println("*************************");
        cust.printURL();
        System.out.println("*************************");
        try {
            cust.printThrowException();
        } catch (Exception e) {

        }

    }
}

customerServiceProxy怎么会是CustomerServicecustomerServiceProxy什么时候继承CustomerService的?
这是Spring使用CGLib实现的。

什么是Advice和Advisor

从上面的例子中我们可以很清楚地明白什么是Advice:HijackBeforeMethod就是Advice, Advice定义了如何对要被注入的方法加入相关的逻辑,比如是在被注入方法的前面加上逻辑,还是在方法的后面。
下面的类使用了aspectj注解:

package test.mine.spring.bean;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SleepHelper {

    @Pointcut("execution(* *.sleep())")
    public void sleeppoint(){}
    
    @Before("sleeppoint()")
    public void beforeSleep(){
        System.out.println("睡觉前要脱衣服!");
    }
    
    @AfterReturning("sleeppoint()")
    public void afterSleep(){
        System.out.println("睡醒了要穿衣服!");
    }    
}

beforeSleep()@Before是Advice,而sleeppoint()(PointCut)和beforeSleep()(包括@Before)是Advisor。

再看问题

  
          
  
  
  
      
          
          
      
  
  
  
      
      
  

对于以上的配置,我们可以在看看另一个例子:


  
  



  

稍微看一些org.springframework.aop.interceptor.CustomizableTraceInterceptor的源码就会知道CustomizableTraceInterceptor实现了MethodInterceptor接口:

public class CustomizableTraceInterceptor extends AbstractTraceInterceptor
public abstract class AbstractTraceInterceptor implements MethodInterceptor, Serializable

那么我们可不可以自己也写一个DataSourceTransactionManagertx:advice?

再看注解的AOP

    @Before("sleeppoint()")
    public void beforeSleep(){
        System.out.println("睡觉前要脱衣服!");
    }

只是在一个方法上加上@Before("sleeppoint()"),就等于:




  
      
      
  
public class BeforeSleepInterceptor implements MethodBeforeAdvice
{
    @Override
    public void before(Method method, Object[] args, Object target)
        throws Throwable {
            System.out.println("BeforeSleepInterceptor : Before method hijacked!");
    }
}

你可能感兴趣的:(深入理解spring的AOP)