1.Aop把一个业务流程分为几个部分,每个部分单独处理,然后把它们组装成完整的业务流程。每个部分都被称为切面或者关注点
2.贴上Aop使用拦截器拦截方法的一个例子;
a)Service接口:
package com.spring.inter;
public interface IAopService {
//定义两个方法
public void withAop() throws Exception;
public void withoutAop() throws Exception;
}
b).Service的实现代码:
package com.spring.impl;
import javax.security.auth.login.AccountException;
import com.spring.inter.IAopService;
public class AopServiceImpl implements IAopService {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* withAop和withoutAop是aspect
*/
@Override
public void withAop() throws Exception {
System.out.println("有Aop的运行函数。name="+name);
if (name.trim().length()==0) {
//构造带指定详细消息的 AccountException(一般用户异常)。详细消息是描述此特定异常的字符串
throw new AccountException("name属性不能为空");
}
}
@Override
public void withoutAop() throws Exception {
System.out.println("没有aop的函数运行");
}
}
c).方法前拦截检查name是否为null
package com.spring.impl;
import java.lang.reflect.Method;
import org.aspectj.weaver.ast.Instanceof;
import org.springframework.aop.MethodBeforeAdvice;
public class MethodBeforeInterceptor implements MethodBeforeAdvice {
/**
* 调用对象的方法钱执行该方法,参数分别为被调用的方法、被调用方法的参数数组,执行方法method的对象的引用
*/
@Override
public void before(Method method, Object[] args, Object obj)
throws Throwable {
System.out.println("即将要执行的方法:"+method.getName());
if (obj instanceof AopServiceImpl) {
String name = ((AopServiceImpl)obj).getName();
if (name==null) {
throw new NullPointerException("name属性不能为空");
}
}
}
}
d).返回后拦截器输出返回值:
package com.spring.impl;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class MethodAfterInterceptor implements AfterReturningAdvice {
/*
* 返回后拦截器输出返回值(non-Javadoc)
* Spring 的后置通知AfterReturning是在方法调用之后织入。但准确的说,通知是在方法返回值之后和方法返回到调用地点之前被织入。
* afterReturning 方法接受目标方法的返回值,目标方法,目标方法需要的参数和目标对象。
* @see org.springframework.aop.AfterReturningAdvice#afterReturning(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
*/
@Override
public void afterReturning(Object value, Method method, Object[] args,
Object obj) throws Throwable {
System.out.println("方法:"+method.getName()+"运行完毕,返回值为:"+value);
}
}
e),异常拦截:
package com.spring.impl;
import java.lang.reflect.Method;
import javax.security.auth.login.AccountException;
import org.springframework.aop.ThrowsAdvice;
public class ThrowsInterceptor implements ThrowsAdvice
{
public void afterThrowing (Method method,Object []args,Object instance,AccountException ex)
{
System.out.println("方法"+method.getName()+"抛出了异常"+ex);
}
public void afterThrowing (NullPointerException ex)
{
System.out.println("抛出了异常"+ex);
}
}
f).拦截器配置:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 配置拦截器对象 -->
<bean id="methodBeforeAdviceImpl" class="com.spring.impl.MethodBeforeAdviceImpl"></bean>
<bean id="theAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<ref local="methodBeforeAdviceImpl"/>
</property>
<property name="mappedName" value="*"></property><!-- 拦截所有的方法 -->
</bean>
<!-- 拦截器在withAop()方法前运行 -->
<bean id="aopBeforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.spring.impl.MethodBeforeInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property><!-- 拦截所有的方法 -->
</bean>
<!-- 拦截器在withAop()方法后运行 -->
<bean id="aopAfterAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.spring.impl.MethodAfterInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property>
</bean>
<!-- 拦截器在异常抛出后运行 -->
<bean id="aopExceptionAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean class="com.spring.impl.ThrowsInterceptor"></bean>
</property>
<property name="mappedName" value="withAop"></property>
</bean>
<bean id="aopService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 拦截器 -->
<property name="interceptorNames">
<list>
<value>aopBeforeAdvisor</value>
<value>aopAfterAdvisor</value>
<value>aopExceptionAdvisor</value>
</list>
</property>
<!-- 被拦截的对象 -->
<property name="target">
<bean class="com.spring.impl.AopServiceImpl">
<property name="name" value="HelloBean"></property>
</bean>
</property>
</bean>
<bean id="daoImpl" class="com.spring.impl.DaoImpl"></bean>
<bean id="serviceImpl" class="com.spring.service.ServiceImpl">
<property name="idao" ref="daoImpl"></property>
</bean>
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames" value="theAdvisor"></property>
<property name="target">
<ref local="serviceImpl"/>
</property>
</bean>
</beans>
提示:组装各类对象时必须使用Spring的代理类,例如ProxyFactoryBean等,这些类能够安装拦截器,而普通的Bean不可以。Spring的代理类还能安装其他的资源,例如数据库的事物管理。
g).测试代码:
XmlBeanFactory factory = new XmlBeanFactory( new ClassPathResource("applicationContext.xml"));
IAopService sopService = (IAopService)factory.getBean("aopService");
sopService.withAop();
sopService.withoutAop();
factory.destroySingletons();
运行结果:
log4j:WARN No appenders could be found for logger (org.springframework.beans.factory.xml.XmlBeanDefinitionReader).
log4j:WARN Please initialize the log4j system properly.
即将要执行的方法:withAop
有Aop的运行函数。name=HelloBean
方法:withAop运行完毕,返回值为:null
没有aop的函数运行
2.拦截器与Filter的区别:
a).使用范围不同,Filter是Servlet规定的,只能使用在web程序中,而拦截器既可以使用在web程序,也可以用于Application、Swing程序中
b).规范不同:Filter 是Servlet固定的,是Servlet容器支持的,而拦截器是Spring容器内的,是Spring框架支持的。
c).使用资源不同:拦截器是一个Spring组件,归Spring管理和配置,配置在spring文件中,因此能使用Spring的任何资源、对象,例如Service对象、数据源、事物管理等,通过IOC注入到拦截器即可,但是Filter则不能。
e).深度不同:Filter只能在Servlet的前后起作用。而拦截器能够深入到方法的前后、异常抛出前后等,因此拦截器具有更大的伸缩性。所以在Spring容器中,要优先使用拦截器。
3.代理模式是Spring中常用的设计模式。Spring提供了几个常用的代理类,例如普通的代理类(ProxyFactoryBean),事物代理类(TransactionProxyFactoryBean)等。