Spring 实现 AOP

[b]用java编写spring通知[/b]

spring中所有的通知都是java类的形式编写,定义在什么地方应用通用的切入点通常编写在spring的配置文件中,而其他框架比如AspectJ,需要特定的语法编写切面和定义切入点,虽然这样可以得到更强大和细致的控制,以及更加丰富的AOP工具,然而,需要学习新工具和语法。

[b]Spring的运行时通知对象[/b]
代理Bean只有在第一次被应用系统需要的时候才被创建,如果使用的是ApplicationContext,代理对象在BeanFactory载入所有Bean的时候创建
Spring有2种代理创建方式
一:如果目标对象实现了一个或多个接口暴露的方法,Spring将使用JDK的java.lang.reflect.Proxy类创建代理,这个类让Spring动态产生一个新的类,它实现了所有的接口,织入了通知,并且代理对目标对象的所有请求。
二:如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类,在创建子类的时候,Spring将通过织入,并且将对目标对象的调用委托给这个子类,使用这种方式应注意两个要点:(1)对接口创建代理优于对类创建代理,因为这样会产生更加松耦合的系统,对类生成代理是让遗留系统或者无法实现接口的第三方类库同样的可以得到通知,这种方式是备用方案(2)标记为final的方法不能被通知,Spring是为目标类产生子类,任何需要被通知的方法都会被复写,将通知织入,final方法是不可能做到的。

[b]Spring 实现了AOP联盟接口[/b]
AOP联盟的目标是标准化AOPjava接口,使各种JavaAop的实现可以互通。

[b]Spring只支持方法连接点[/b]
AspectJ和Jboss提供了属性接入点,Spring的观点是属性拦截破坏了封装,面向对象的基本概念是对象自己处理工作,其他对象只能通过方法调用得到处理结果。

[b]创建Spring通知[/b]
基本通知有以下几种:
一:Around----org.aopllliance.intercept.MethodInterceptor
拦截对目标对象方法调用
二:Before----org.springframework.aop.BeforeAdvice
在目标方法被调用前调用
三:After------org.springframework.aop.AfterRetruningAdvice
在方法被调用之后调用
四:Throws----org.springframework.aop.ThrowsAdvice
在目标方法抛出异常时调用
通知事例:

(1)接口类 SimpleInterface
public interface SimpleInterface{
Home getPerHome(Person person) throws NoPersonException;
}

(2)实现类
public class SimpleClass implements SimpleInterface{
private boolean noHome;
public Home getPerHome(Person person)throws NoPersonException{
if(person.getName().eq("")){
thorws new EmptyPersonException();
}
return person.getHome();
}
}


(3)前置通知
我们的目标是在getPerHome方法调用之前,先打印出用户Person的姓名
public class BeforeAdvice implements MethodBeforeAdvice{
public void before(Method method,Object[] args,Object target){
Person person = (Person)args[0];//因为getPerHOme方法中只有一个参数,我们将第一个参数转换为Person对象
System.out.println(person.getName());
//在方法结束后不返回任何结果,因为它返回后目标方法将被调用。
}
}
MethodBeforeAdvice唯一能阻止目标方法被调用的途径是抛出异常,或者调用System.exit();抛出异常的结果依赖异常的类型,如果是runtimeException或者目标方法声明的异常,异常将传播到调用方法,否则Spring框架将捕获异常,并重新包装在RuntimeException中再次抛出
(4)配置目标对象
<beans>
//创建代理的目标对象
<bean id="simpleClassTarget" class="SimpleClass"/>
//创建通知
<bean id="myadvice" class="BeforeAdvice"/>
//创建代理
<bean id="sipleClassProxy" class="org.springframework.aop.
framework.ProxyFactoryBean">
//要实现的接口
<property name="proxyInterfaces">
<value>SimpleInterface</value>
</property>
//被织入的通知
<property name="interceptorNames">
<list>
<value>myadvice</value>
</list>
</property>
//被代理的目标对象
<property name="target">
<ref bean=""/>
</property>
</bean>
</beans>
ProxyFactoryBean类是一个在BeanFactory中显示地创建代理对象的中心类,给它一个要实现的接口,一个要代理的目标对象,一个要织入的通知,它将创建一个崭新的代理对象,通常配置ProxyFactoryBean,让它实现和目标对象一样的接口。

(5)后置通知
我们的目标是在getPerHome方法调用之前,先打印出成功提示。
public class AfterAdvice implements AfterReturnningAdvice {
public void afterReturnning(Object returnValue,Method method,
Object [] arg,Object target)throws Throwable{
System.out.println("scusess");
}
}

(6)环绕通知
目标,我们想控制目标方法是否被调用以及控制返回的对象。
具体要求,SimpleClass 得getPerHome方法只能返回CurPerson的name不为null的Home.
public class myInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation invoca)throws Throwable{
//得到当前的Person
Person person = (Person)invoca.getArguments[0];
//判断是否满足目标要求
if(person.name == "CuiPerson"){
throws new UserCustomException();
}
//调用目标方法
Object home = invoca.proceed();
reuturn home ;
}
}

此接口是AOP联盟接口 ,它在目标方法的前后都有逻辑操作,但你必须显示的调用invoca.proceed();方法
(7)异常通知
目标,我们想在执行目标方法抛出异常时打印出异常的出现时间
ThrowsAdvice是一个标示接口,没有任何必须实现的接口,但这个接口必须有一个如下形式的方法:
void afterThrowing(Throwable throwable);
//被调用的方法,参数,目标对象
void afterThrowing(Method method,Object[] args,Object target,
Throwable throwable)

例如:afterThrowing(MyException e),将捕获所有的MyException异常。因此你可以在类中实现多个afterThrowing方法,处理不同的异常。

具体实现代码:
public class MyExceptionAdevice implements ThrowsAdvice{
public void afterThrowing([b]EmptyPersonException[/b] e){
System.out.println(new Date().toString);
}
}

注:ThrowAdvice被执行后,原来的异常继续抛出,并且象其他异常一样被传播出去,ThrowAdvice能做的改变是抛出另外一个异常

(8)引入通知
引入通知是给目标对象添加新的方法以及属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值