在 Intellij Idea 环境下初探 Spring Core (二) 之 AOP

说说

在 Intellij Idea 环境下初探 Spring Core (一) 之 IoC/DI 中, 我学会了使用 Spring 的 IoC 功能. 这篇文字写的是 AOP 功能.

AOP 的几种形式

当一个方法要执行的时候, Spring AOP 可以在方法执行之前或之后添加额外的执行方法. Spring AOP支持四种形式的AOP.

  1. 在方法执行之前拦截
  2. 在方法执行之后拦截
  3. 在抛出异常的时候拦截
  4. 包括以上三种拦截的拦截

在 Intellij idea 中体验 Spring AOP

  • 继续使用 (一) 中的工程
  • 在 com.jecvay.springhello 包中添加一个类 HijeckBeforeHello, 代码如下. 这个类就是要通过AOP在HelloWorld类的任何一个方法运行之前插入一段显示 Hiject before Hello world! 的代码.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    package com.tutorialspoint;
    import org.springframework.aop.MethodBeforeAdvice;
    import java.lang.reflect.Method;
    public class HijackBeforeHello implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target)
    throws Throwable {
    System.out.println("Hiject before Hello world!");
    }
    }
    package com.tutorialspoint; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class HijackBeforeHello implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("Hiject before Hello world!"); } }
    package com.tutorialspoint;
    import org.springframework.aop.MethodBeforeAdvice;
    import java.lang.reflect.Method;
    
    public class HijackBeforeHello implements MethodBeforeAdvice {
      @Override
      public void before(Method method, Object[] args, Object target)
             throws Throwable {
          System.out.println("Hiject before Hello world!");
      }
    }
  • 配置 Beans.xml, 因为这里AOP使用的是 CGLIB 动态代理, 所以相应的要在Beans中配置一个代理. 在 前插入如下代码
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <bean id="hijeckBeforeHello" class="com.tutorialspoint.HijackBeforeHello" />
    <bean id="helloServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="helloWorld" />
    <property name="interceptorNames">
    <list>
    <value>hijeckBeforeHello</value>
    </list>
    </property>
    </bean>
    <bean id="hijeckBeforeHello" class="com.tutorialspoint.HijackBeforeHello" /> <bean id="helloServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="helloWorld" /> <property name="interceptorNames"> <list> <value>hijeckBeforeHello</value> </list> </property> </bean>
    <bean id="hijeckBeforeHello" class="com.tutorialspoint.HijackBeforeHello" />
        <bean id="helloServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="helloWorld" />
            <property name="interceptorNames">
                <list>
                    <value>hijeckBeforeHello</value>
                </list>
            </property>
        </bean>
  • 修改 MainApp 类, 用代理替换原本 HelloWorld 类型的 obj 对象:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    HelloWorld obj = (HelloWorld) context.getBean("helloServiceProxy");
    obj.getMsg();
    obj.getMsg();
    obj.getMsg();
    HelloWorld obj = (HelloWorld) context.getBean("helloServiceProxy"); obj.getMsg(); obj.getMsg(); obj.getMsg();
        HelloWorld obj = (HelloWorld) context.getBean("helloServiceProxy");
        obj.getMsg();
        obj.getMsg();
        obj.getMsg();
  • 运行结果如下所示:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    Hiject before Hello world!
    Hello, Jecvay
    Hiject before Hello world!
    Hello, Jecvay
    Hiject before Hello world!
    Hello, Jecvay
    Hiject before Hello world! Hello, Jecvay Hiject before Hello world! Hello, Jecvay Hiject before Hello world! Hello, Jecvay
    Hiject before Hello world!
    Hello, Jecvay
    Hiject before Hello world!
    Hello, Jecvay
    Hiject before Hello world!
    Hello, Jecvay

Tips

  • 如果想在方法执行完毕后拦截, 只要写一个继承 MethodAfterAdvice 的类, 然后配置同样的 Bean 即可.
  • 如果想在方法抛出异常的时候拦截, 则继承 ThrowsAdvice 类, 要插入的方法的参数就是要拦截的异常对象.
  • 如果想在一个拦截器中拦下上述三种情况, 则继承 MethodInterceptor 类, before 的直接写在开头, after 的写在 methodInvocation.proceed(); 之后, 异常的直接写在 try … catch 的 catch 中.

其他

从工程结构来看, 尤其是 Beans.xml 的配置来看, Spring AOP 是建立在 IoC 的基础之上的. 在程序运行后, 由 Spring 框架来产生提供 AOP 的代理模块, 并注入到 main 方法中.

实现AOP的其他方法

Spring AOP + AspectJ 方案可以让我们基于注解实现 AOP, 非常方便.
http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/


本文链接

回复