Spring AOP

前面又是讲代理,又是讲AOP;又是讲静态,又是讲动态;又是讲jdk aop,又是讲cglib;又是讲aspectj,又是讲其它。其实都是为了这一篇做铺垫。

  • spring aop 的简单例子

我们还是以一个简单的例子来观察一下spring aop究竟是长得什么样。

  1. pom文件
  
            org.springframework
            spring-context
            ${springframework.version}
        
        
            org.springframework
            spring-aop
            ${springframework.version}
        
        
            org.aspectj
            aspectjrt
            1.6.12
        
        
            org.aspectj
            aspectjweaver
            1.6.12
        

需要引入aop模块和aspectj相关的包。

  1. xml文件

    
    
    
    
    

一定要开启

  1. Java接口和实现
public interface IHelloService {
    void sayHello();
}

@Service("helloService")
public final class HelloService implements IHelloService{
    @Override
    public void sayHello(){
        System.out.println("hello world");
    }
}
  1. 最重要的切面类
@Component
@Aspect
public class AopConfig {
    @Before(value = "execution(* com.huangzp.test.aop.*.sayHello(..))")
    public void sayHello(){
        System.out.println("我是Aop config");
    }
}

定义一个切面类,定义一个前置通知的切入点,可以看到它的语法和aspectj是如此的相似。

  1. 测试运行
public class AopMain {
    public static void main(String[] args) {
        //创建容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取personService的bean
        IHelloService helloService = (IHelloService)applicationContext.getBean("helloService");
        //调用方法
        helloService.sayHello();
    }
}
  • spring aop的底层实现

在Spring的底层,如果我们配置了代理模式,Spring会用ProxyFactoryBean为每一个Bean创建一个代理对象,如果是实现了接口的bean,那么创建的是JdkDynamicAopProxy;如果不是,则创建CglibAopProxy。
我们可以模拟一下实现:

  1. 模拟JdkDynamicAopProxy
//Java接口和实现类
public interface JDKHelloService {
    void sayHello();
}
public class JDKHelloServiceImpl implements JDKHelloService{
    @Override
    public void sayHello() {
        System.out.println("hello jdk aop");
    }
}

//定义一个前置通知
public class AdviceBefore implements MethodBeforeAdvice{
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我是前置通知");
    }
}

//用ProxyFactoryBean来实验一下
    public static void main(String[] args) {
        //生成前置通知
        Advice advice = new AdviceBefore();
        //目标对象
        JDKHelloService jdkHelloService = new JDKHelloServiceImpl();
        //创建ProxyFactoryBean
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        //设置目标对象,设置接口和添加通知
        proxyFactoryBean.addAdvice(advice);
        proxyFactoryBean.setInterfaces(JDKHelloService.class);
        proxyFactoryBean.setTarget(jdkHelloService);
        //生成代理并且运行
        JDKHelloService helloService = (JDKHelloService)proxyFactoryBean.getObject();
        helloService.sayHello();
    }

我们在下面的helloService.sayHello();设置断点并且进入,可以看到


这个和我们之前的jdk aop 很像,我们设置保存代理文件得到的$proxy0和在jdk aop拿到的是一样的,在$proxy0中sayHello也是调用Proxy的InvocationHandler成员变量的invoke方法,那么这回什么实现了InvocationHandler?当然就是我们的JdkDynamicAopProxy。

  1. 模拟 CglibAopProxy
//目标对象,java实现类
public class CGLibHelloService {
    public void sayHello(){
        System.out.println("hello cglib aop");
    }
}

//定义一个前置通知
public class AdviceBefore implements MethodBeforeAdvice{
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我是前置通知");
    }
}

//用ProxyFactorybean来测试一下
    public static void main(String[] args) {
        //生成前置通知
        Advice advice = new AdviceBefore();
        //目标对象
        CGLibHelloService cgLibHelloService = new CGLibHelloService();
        //创建ProxyFactoryBean
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        //设置目标对象和添加通知
        proxyFactoryBean.addAdvice(advice);
        proxyFactoryBean.setTarget(cgLibHelloService);
        //生成代理并且运行
        CGLibHelloService helloService = (CGLibHelloService)proxyFactoryBean.getObject();
        helloService.sayHello();
    }

我们在最下面的helloService.sayHello()设置短点并且进入,可以看到



实际上还是用的ehancer动态创建的子类对象 和 方法拦截实现的cglib动态代理,只是这回之前的MyProxy代理类换成了CglibAopProxy。

你可能感兴趣的:(Spring AOP)