您的位置:首页 > 编程语言 > Java开发

白话Spring(基础篇)---AOP(实例篇-2)

2016-03-05 10:20 471 查看
[一知半解,就是给自己挖坑]

在AOP(实例篇-1)中,我们演示了针对某个类对象的全部方法进行AOP切面处理,接下来,我们来演示一下,如何在一个类对象中,只针对某个方法进行AOP切面处理。

准备工作:

a.操作系统:win7 x64

b.开发工具:eclipse mars j2ee版本,maven3.3.2,Spring 4,junit4.12
c.工程仍然是上一个Spring091。
-------------------------------------------------------------------------------------------------------------------------------------

1.创建Pointcut.java文件,具体内容如下:

package com.java.ingo.point;

import java.lang.reflect.Method;
import org.springframework.aop.support.NameMatchMethodPointcut;
/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日上午11:43:23
*类说明
*/
public class Pointcut extends NameMatchMethodPointcut {

private static final long serialVersionUID = 3990456017285944475L;
@SuppressWarnings("rawtypes")
public boolean matches(Method method, Class targetClass) {
// 设置单个方法匹配
this.setMappedName("delete");
// 设置多个方法匹配
String[] methods = { "delete","modify" };
//也可以用“ * ” 来做匹配符号
// this.setMappedName("get*");
this.setMappedNames(methods);
return super.matches(method, targetClass);
}
}
2.修改beans.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">

<!-- ==============================利用spring自己的aop配置================================ -->
<!-- 声明一个业务类 -->
<bean id="baseBusiness" class="com.java.ingo.service.impl.BaseBusiness" />
<!-- 声明通知类 -->
<bean id="baseBefore" class="com.java.ingo.advice.BaseBeforeAdvice" />
<bean id="baseAfterReturn" class="com.java.ingo.advice.BaseAfterReturnAdvice" />
<bean id="baseAfterThrows" class="com.java.ingo.advice.BaseAfterThrowsAdvice" />
<bean id="baseAround" class="com.java.ingo.advice.BaseAroundAdvice" />
<!-- 指定切点匹配类 -->
<bean id="pointcut" class="com.java.ingo.point.Pointcut" />

<!-- 前置通知-->
<bean id="matchBeforeAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut">
<ref bean="pointcut" />
</property>
<property name="advice">
<ref bean="baseBefore" />
</property>
</bean>

<!-- 后置通知-->
<bean id="matchAfterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="patterns">
<list>
<value>.*delete</value>
</list>
</property>
<property name="advice">
<ref bean="baseAfterReturn" />
</property>
</bean>

<!-- 环绕通知-->
<bean id="matchAroundAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedNames">
<list>
<value>delete</value>
</list>
</property>
<property name="advice">
<ref bean="baseAround" />
</property>
</bean>

<!-- 使用ProxyFactoryBean 产生代理对象 -->
<bean id="businessProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理对象所实现的接口 ,如果有接口可以这样设置 -->
<property name="proxyInterfaces">
<value>com.java.ingo.service.IBaseBusiness</value>
</property>

<!-- 设置目标对象 -->
<property name="target">
<ref local="baseBusiness" />
</property>
<!-- 代理对象所使用的拦截器 -->
<property name="interceptorNames">
<list>
<value>matchBeforeAdvisor</value>
<value>matchAfterAdvisor</value>
<value>matchAroundAdvisor</value>
</list>
</property>
</bean>
</beans>
我们来看看配置文件中各个配置项的含义:

a.首先,我们先定义了需要我们加入AOP的对象,设置id为baseBusiness。

b.接着,定义了4个不同类型的通知,通知分别继承于AOP接口,具体内容请查看前文详情

c.然后,我们分别定义了通知类型的作用范围,注意观察每一种通知范围的配置方式。

d.最后,设置ProxyFactoryBean。具体解释请查看代码中的注释部分

3.修改IBaseBusiness.java文件,具体内容如下:

package com.java.ingo.service;

import com.java.ingo.entity.Customer;
/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月5日上午10:40:25
*类说明
*/
public interface IBaseBusiness {

public void delete(Customer obj);

public String add(String obj);

public void modify(Customer customer);

}


4.修改BaseBusiness.java,具体内容如下:

public class BaseBusiness implements IBaseBusiness {

/**
* 切入点
*/
public void delete(Customer obj) {
System.out.println("||///////////////////||");
System.out.println("删除用户:"+obj.getName());
System.out.println("||///////////////////||");
}

public String add(String add) {
System.out.println("||///////////////////||");
System.out.println("add用户:"+add);
System.out.println("||///////////////////||");
return add;
}

public void modify(Customer obj) {
System.out.println("|///////////////////||");
System.out.println("modify用户:"+obj.getName());
System.out.println("|///////////////////||");
}

}


5.测试方法:运行main方法,分别执行接口中提供的三种方法,观察控制台输出即可。

-------------------------------------------------------------------------------------------------------------------------------------

备注:

1.后置通知中拦截规则:

后置通知中的bean下的patterns属性下添加一些正则表达式规则,能够匹配这些规则的方法就会被拦截。值得一提的是,这儿匹配的是方法的完整路径,包括类名已经类的包名。回顾一下,这儿的目标类是com.java.ingo.service.impl,它里面只有三个方法add,delete,modify。这三个方法的完整路径就是com.java.ingo.service.impl.BaseBusiness.add
和 com.java.ingo.service.impl.BaseBusiness.add .delete等 。这儿写的正则表达式是.*delete,明显它可以匹配com.java.ingo.service.impl.BaseBusiness.add .delete,所以这个方法会被拦截。假设将正则表达式写成delete,那么它不能匹配com.java.ingo.service.impl.BaseBusiness.add .delete 这整个字符串,所以讲不会起作用。如果要拦截方法名中包含abc的方面,正则表达式写成.*abc.*就可以了(当然包名和类名不能是abc)

2.环绕通知通的拦截规则:

环绕通知中可以用*通配符,如,*User就代表所有以User结尾的方法。注意这儿只匹配方法名,不会管类名和包名了。

-------------------------------------------------------------------------------------------------------------------------------------

至此,白话Spring(基础篇)---AOP(实例篇-2)结束。

参考资料:

Spring官网:http://spring.io/docs
其他博文: http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example http://tonl.iteye.com/blog/1966075
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: