一、 Spring AOP术语概述
1、 切面(aspect):要实现的交叉功能,是系统模块化的一个切面或领域。如日志记录。
2、 连接点:应用程序执行过程中插入切面的地点,可以是方法调用,异常抛出,或者要修改的字段。
3、 通知:切面的实际实现,他通知系统新的行为。如在日志通知包含了实现日志功能的代码,如向日志文件写日志。通知在连接点插入到应用系统中。
4、 切入点:定义了通知应该应用在哪些连接点,通知可以应用到AOP框架支持的任何连接点。
5、 引入:为类添加新方法和属性。
6、 目标对象:被通知的对象。既可以是你编写的类也可以是第三方类。
7、 代理:将通知应用到目标对象后创建的对象,应用系统的其他部分不用为了支持代理对象而改变。
8、 织入:将切面应用到目标对象从而创建一个新代理对象的过程。织入发生在目标对象生命周期的多个点上:
编译期:切面在目标对象编译时织入.这需要一个特殊的编译器.
类装载期:切面在目标对象被载入JVM时织入.这需要一个特殊的类载入器.
运行期:切面在应用系统运行时织入.
二、 Spring的AOP实现:用Java编写Spring通知
创建通知
通知类型 | 接口 | 描述 |
Around | Org.springframework.aop. MethodInterceptor | 拦截对目标方法调用 |
Before | Org.springframework.aop. BeforeAdvice | 在目标方法调用前调用 |
After | Org.springframework.aop. AfterReturningAdvice | 在目标方法调用后调用 |
Throws | Org.springframework.aop. ThrowsAdvice | 当目标方法抛出异常时调用 |
三、下面是用一个实例来演示其五个通知的用法:
需要的jar:如下如所示:
在写通知之前,我们要写一个PersonService.java接口,在其中实现一个方法,代码如下:
import java.util.Date;
publicinterface PersonService {
//学习课程及开始日期
publicvoid study(String name,Date startTime);
}
在写一个实现其接口的实现类:PersonServiceBean.java,代码如下:
import java.util.Date;
publicclass PersonServiceBean implements PersonService{
@Override
publicvoid study(String name, Date startTime) {
System.out.println("学习的科目是:"+name+" 学习的开始时间是:"+startTime);
//(实现异常通知使用时)
/* try{
int i=1/0;
}catch(Exception e){
//
}*/
System.out.println("=============");
}
}
(一)环绕通知:
如果想要实现环绕通知,就要实现Org.springframework.aop.MethodInterceptor。
1) 下面我们要自己定义一个环绕通知MyAroundAdvice。代码如下:
publicclassMyAroundAdvice implements MethodInterceptor {
@Override
publicObject invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("执行方法之前执行操作");
Object obj = methodInvocation.proceed();//执行目标方法
System.out.println("执行方法之后执行操作");
return obj;
}
}
2) 下面我们要对环绕通知进行配置,在beans.xml文件中进行配置。如下代码:
<!-- 环绕通知 -->
<bean id="myAroundAdvice"class="cn.csdn.hr.advice.MyAroundAdvice"/>
<!-- 业务bean -->
<bean id="personServiceBean"class="cn.csdn.hr.service.PersonServiceBean"/>
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的接口 -->
<propertyname="proxyInterfaces">
<list>
<value>cn.csdn.hr.service.PersonService</value>
</list>
</property>
<!-- 通知名称-->
<propertyname="interceptorNames">
<list>
<value>myAroundAdvice</value>
</list>
</property>
<!--通知的对象 -->
<propertyname="target">
<refbean="personServiceBean"/>
</property>
(二)前置通知:
1)下面我们要自己定义一个环绕通知MyBeforeAdvice.java。代码如下:
publicclass MyBeforeAdviceimplements MethodBeforeAdvice{
@Override
publicvoid before(Method method, Object[] args, Object target)
throws Throwable {
//第一个参数方法对象
//第二个参数:方法参数
//第三个对象:目标对象
Object obj =null;
if(args.length>0){
obj= args[0];
}
System.out.println("before-----------方法的名称:::"+method.getName()+" 方法的第一个参数值"+obj.toString()+" 目标对象是:"+target.getClass());
//可以再执行目标方法之前执行此操作
}
}
2)下面我们要对环绕通知进行配置,在beans.xml文件中进行配置。如下代码:
<!-- 配置前置通知 -->
<beanid="myBeforeAdvice"class="cn.csdn.hr.advice.MyBeforeAdvice"/>
<!-- 业务bean -->
<beanid="personServiceBean"class="cn.csdn.hr.service.PersonServiceBean"/>
<beanid="proxyFactoryBean"class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的接口 -->
<propertyname="proxyInterfaces">
<list>
<value>cn.csdn.hr.service.PersonService</value>
<value>cn.csdn.hr.service.Auditable</value>
</list>
</property>
<!-- 通知名称-->
<propertyname="interceptorNames">
<list>
<value>myBeforeAdvice</value>
</list>
</property>
<!--通知的对象 -->
<propertyname="target">
<refbean="personServiceBean"/>
</property>
(三)后置通知:
1)下面我们要自己定义一个环绕通知MyAfterAdivce.java。代码如下:
publicclass MyAfterAdivce implements AfterReturningAdvice{
@Override
publicvoid afterReturning(Object returnValue, Method method,
Object[] args, Object target)throws Throwable {
//执行目标方法之后执行此操作
System.out.println("after---------------------方法的返回值是:"+returnValue);
}
}
2)下面我们要对后置通知进行配置,在beans.xml文件中进行配置。如下代码:
<!-- 配置后置通知 -->
<beanid="myAfterAdivce"class="cn.csdn.hr.advice.MyAfterAdivce"/>
<!-- 业务bean -->
<beanid="personServiceBean"class="cn.csdn.hr.service.PersonServiceBean"/>
<beanid="proxyFactoryBean"class="org.springframework.aop.framework.ProxyFactoryBean">
<!--代理的接口 -->
<propertyname="proxyInterfaces">
<list>
<value>cn.csdn.hr.service.PersonService</value>
<value>cn.csdn.hr.service.Auditable</value>
</list>
</property>
<!-- 通知名称-->
<propertyname="interceptorNames">
<value>myAfterAdivce</value>
</list>
</property>
<!--通知的对象 -->
<propertyname="target">
<refbean="personServiceBean"/>
</property>
(四)异常通知:
1)下面我们要自己定义一个异常通知MyThrowsAdivce.java。代码如下:
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdivce implements ThrowsAdvice {
/*public void afterThrowing(Throwable throwable){
}*/
//异常处理操作
public void afterThrowing(Method method,Object[] args, Object target,Throwable throwable){ System.out.println("exception----------------------------"+throwable.getMessage());
}
}
2)下面我们要对环绕通知进行配置,在beans.xml文件中进行配置。如下代码:
<!-- 配置异常通知 -->
<beanid="myThrowsAdivce"class="cn.csdn.hr.advice.MyThrowsAdivce"/>
<!-- 业务bean -->
<beanid="personServiceBean"class="cn.csdn.hr.service.PersonServiceBean"/>
<beanid="proxyFactoryBean"class="org.springframework.aop.framework.ProxyFactoryBean">
<!--代理的接口 -->
<propertyname="proxyInterfaces">
<list>
<value>cn.csdn.hr.service.PersonService</value>
<value>cn.csdn.hr.service.Auditable</value>
</list>
</property>
<!-- 通知名称-->
<propertyname="interceptorNames">
<list>
<value>myThrowsAdivce</value>
</list>
</property>
<!--通知的对象 -->
<propertyname="target">
<refbean="personServiceBean"/>
</property>
(五)引入通知:
1)下面我们要自己定义一个引入通知的接口的声明。代码如下:
import java.util.Date;
//添加一个属性 记录最后一次修改的时间的操作
publicinterface Auditable {
void setLastModifiedDate(Date lastModifiedDate);
Date getLastModifiedDate();
}
2)下面我们要自己定义一个引入通知AuditableAdvice.java继承DelegatingIntroductionInterceptor这个类并且要实现自己定义的接口Auditable。代码如下:
import java.util.Date;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
/**
*
* 引入通知(引入的拦截器)
*
*/
public class AuditableAdvice extends DelegatingIntroductionInterceptor implements Auditable{
private Date lastModifiedDate;
@Override
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate=lastModifiedDate;
}
@Override
public Date getLastModifiedDate() {
return lastModifiedDate;
}
}
3)下面我们要对引入通知进行配置,在beans.xml文件中进行配置。如下代码:
<!-- 引入通知 -->
<bean id="auditableAdvice" class="cn.csdn.hr.advice.AuditableAdvice"/>
<!-- 业务bean -->
<bean id="personServiceBean" class="cn.csdn.hr.service.PersonServiceBean"/>
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的接口 -->
<property name="proxyInterfaces">
<list>
<value>cn.csdn.hr.service.PersonService</value>
<value>cn.csdn.hr.advice.Auditable</value>
</list>
</property>
<!-- 通知名称-->
<property name="interceptorNames">
<list>
<value>auditableAdvice</value>
</list>
</property>
<!-- 通知的对象 -->
<property name="target">
<ref bean="personServiceBean"/>
</property>