Spring AOP 的简单例子

来源:互联网 发布:手机淘宝差评怎么删 编辑:程序博客网 时间:2024/05/16 08:46

Spring AOP 的简单例子

       Spring AOP 实现了AOP联盟(Alliance)的制定的接口规范,它基于java的代理机制实现。AOP作为Spring的核心技术之一. 更多关于Spring AOP介绍 可参考:http://oss.org.cn/ossdocs/framework/spring/zh-cn/aop.html  下面给出一个例子来简单介绍Spring AOP具体实现过程

    现假设用户通过login.jsp页面输入相应的用户名和密码之后,首先Spring AOP的环绕通知验证该用户名和密码是否符合要求,若符合要求,则到数据库中查找该用户,若用户存在,将该用户相关的信息写入日志。

1.BaseLoginAdvice 类实现了 前置通知接口(MethodBeforeAdvice)、环绕通知接口(MethodInterceptor)、后置通知接口(AfterReturningAdvice) 这三个接口

BaseLoginAdvice.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.laoyangx.Aop.chapter0;
 
import java.lang.reflect.Method;
 
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
 
public abstract class BaseLoginAdviceimplements MethodBeforeAdvice, MethodInterceptor,
        AfterReturningAdvice {
    /**
     * @param returnValue 目标方法返回值
     * @param method 目标方法
     * @param args 方法参数
     * @param target 目标对象
     *
     */
    @Override
    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
         
         throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
    }
     
     
    /**
     * @param invocation 目标对象的方法
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
         
        throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
    }
 
    /**
     * @param method 将要执行的目标对象方法
     * @param args 方法的参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
         
        throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
    }
 
}

2.LoginAdviceSupport 类继承 BaseLoginAdvice 类,并重写 BaseLoginAdvice 类的三个方法

LoginAdviceSupport.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.laoyangx.Aop.chapter0;
 
import java.lang.reflect.Method;
 
import org.aopalliance.intercept.MethodInvocation;
 
public class LoginAdviceSupportextends BaseLoginAdvice {
 
    /**
     * 若在数据库中存在指定的用户,将用户登录信息写入日志文件
     * @param returnValue 目标方法返回值
     * @param method 目标方法
     * @param args 方法参数
     * @param target 目标对象
     */
    @Override
    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
         
       System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:afterReturning ----------------");
       
       //将用户登录信息写入日志文件
    }
    
    /**
     * 验证用户输入是否符合要求
     * @param invocation 目标对象的方法
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
         
        System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:invoke ----------------");
         
        String username=invocation.getArguments()[0].toString();
        String password=invocation.getArguments()[1].toString();
         
        //在这里进行相关的验证操作 
         
        //假设验证通过
        return invocation.proceed();
    }
 
    /**
     * 在数据库中查找指定的用户是否存在
     * @param method 将要执行的目标对象方法
     * @param args 方法的参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
         
        System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:before ----------------");
     
         String username=(String)args[0];
         String passowrd=(String)args[1];
          
        //在这里进行数据库查找操作
    }
}

3. IUser.java

1
2
3
4
5
6
7
8
9
10
package com.laoyangx.Aop.chapter0;
 
public interface IUser {
    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     */
  public void Login(String username,String password);
}

4.UserImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.laoyangx.Aop.chapter0;
 
public class UserImplimplements IUser {
 
    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     */
    @Override
    public void Login(String username, String password) {
        System.out.println("---------- 程序正在执行  类名: com.laoyangx.Aop.chapter0.UserImpl 方法名:Login ----------------");
    }
 
}

5. Spring 的配置文件 login.bean.xml

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop
="http://www.springframework.org/schema/aop"
xmlns:tx
="http://www.springframework.org/schema/tx"
xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
>

<bean id="loginAdvice" class="com.laoyangx.Aop.chapter0.LoginAdviceSupport"></bean>
<bean id="userTarget" class="com.laoyangx.Aop.chapter0.UserImpl"></bean>

<bean id="user" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.laoyangx.Aop.chapter0.IUser</value>
</property>
<property name="interceptorNames">
<list>
<value>loginAdvice</value>
</list>
</property>
<property name="target">
<ref bean="userTarget"/>
</property>
</bean>


</beans>
复制代码

6.主程序文件 ConsoleApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.laoyangx.Aop.chapter0;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class ConsoleApp {
 
 
    public static void main(String[] args) {
         
        ApplicationContext ctx=
            new ClassPathXmlApplicationContext("com/laoyangx/Aop/chapter0/login.bean.xml");
         
        IUser user=(IUser)ctx.getBean("user");
        user.Login("username","123456");
 
    }
 
}

运行程序之后,控制台上输出的结果

通过结果可以看到每个函数的执行顺序。关于 前置通知、环绕通知、后置通知 这些术语 网上都有相关的介绍

0 0