我和春天有个约会(四)
来源:互联网 发布:pro recorder替代软件 编辑:程序博客网 时间:2024/04/25 18:08
Spring AOP头绪众多,先从基本观念入手。
Spring AOP基本要务
悄悄地我走了,正如我悄悄地来……
AOP是OOP之后编程思想的又一次变革。在AOP的编程模型中对象A正交地“横切”到对象B的生命周期当中,而B对此却浑然不知,这样以“Aspect”的方式提高了类的重用性、灵活性以及可维护性,毕竟不用对B再动手脚,只要让它做好自己的本职工作,额外的事情交给A来完成。动态代理初步实现了这一点,而Spring AOP提供的方式却更为丰富而灵活。
Spring AOP的几个基本点就是Advice、Target、Proxy。Spring AOP的实现基于动态代理,因此理解后者有助于理解前者。
坐而论道不如躬身实践,如下HelloSpeaker就是那个对Aspect浑然不知的傻小子,我们称为Target。为了验证后面的ThrowsAdvice,我故意在参数为空时抛出异常。
public class HelloSpeaker implements IHello ...{
public String say_hello(String msg) ...{
if (msg == null || msg.equals("")) ...{
throw new NullPointerException("The arg is null...");
} else ...{
System.out.println("hello," + msg + "!");
}
return "succeed";
}
}
public String say_hello(String msg) ...{
if (msg == null || msg.equals("")) ...{
throw new NullPointerException("The arg is null...");
} else ...{
System.out.println("hello," + msg + "!");
}
return "succeed";
}
}
IHello是从HelloSpeaker引出的接口,这也是HelloSpeaker和Aspect唯一相接的地方,正是凭借这个接口,Target被Aspect玩弄于股掌。
public interface IHello ...{
public String say_hello(String msg);
}
public String say_hello(String msg);
}
下面几个类就是所谓的Advice,Advice就是“横切”的具体行为,如提供日志服务、权限管理等,它们在各种AOP实现中被织入(Weave)主体业务中。
AfterReturningAdvice接口的afterReturning方法在Target方法之后运行;MethodBeforeAdvice接口的before方法在Target方法之前运行;MethodInterceptor的invoke方法更为霸道,除了可在前后修饰之外还决定Target方法的运行,这个做法就类似于动态代理了。
ThrowsAdvice接口有些特殊,并无接口方法,只要实现接口者提供afterThrowing方法,并在方法中提供Throwable参数,并且可选method、target、args等参数。另外该接口并不改变原有的异常处理流程。
public class LogAfterAdvice implements AfterReturningAdvice ...{
public void afterReturning(Object obj_res, Method method, Object[] args, Object target) throws Throwable ...{
String res = (String) obj_res;
System.out.println("method " + method.getName() + " ends,res..." + res);
}
}
public class LogAroundAdvice implements MethodInterceptor ...{
public Object invoke(MethodInvocation method_invocation) throws Throwable ...{
System.out.println("In method-intercept, before method");
Object res = null;
try ...{
res = method_invocation.proceed();
} finally ...{
System.out.println("In method-intercept, Method "
+ method_invocation.getMethod().getName() + " end.");
}
return res;
}
}
public class LogBeforeAdvice implements MethodBeforeAdvice ...{
public void before(Method method, Object[] args, Object target)
throws Throwable ...{
System.out.println("Before " + method.getName() + " starts");
}
}
public class LogExceptionAdvice implements ThrowsAdvice ...{
public void afterThrowing(Method method, Object[] args, Object target, Throwable e) ...{
System.out.println("Exception " + e + ":"
+ " occurs at method " + method.getName());
}
}
public void afterReturning(Object obj_res, Method method, Object[] args, Object target) throws Throwable ...{
String res = (String) obj_res;
System.out.println("method " + method.getName() + " ends,res..." + res);
}
}
public class LogAroundAdvice implements MethodInterceptor ...{
public Object invoke(MethodInvocation method_invocation) throws Throwable ...{
System.out.println("In method-intercept, before method");
Object res = null;
try ...{
res = method_invocation.proceed();
} finally ...{
System.out.println("In method-intercept, Method "
+ method_invocation.getMethod().getName() + " end.");
}
return res;
}
}
public class LogBeforeAdvice implements MethodBeforeAdvice ...{
public void before(Method method, Object[] args, Object target)
throws Throwable ...{
System.out.println("Before " + method.getName() + " starts");
}
}
public class LogExceptionAdvice implements ThrowsAdvice ...{
public void afterThrowing(Method method, Object[] args, Object target, Throwable e) ...{
System.out.println("Exception " + e + ":"
+ " occurs at method " + method.getName());
}
}
维系各个Advice和Target的纽带就是Proxy,在这里就是ProxyFactoryBean,定义在配置文件当中。在这个代理当中指定Target及其interface,指定了各类advice。
<bean id="logBeforeAdvice" class="onlyfun.caterpillar.aop.LogBeforeAdvice"/>
<bean id="logAfterAdvice" class="onlyfun.caterpillar.aop.LogAfterAdvice"/>
<bean id="logInterceptor" class="onlyfun.caterpillar.aop.LogAroundAdvice"/>
<bean id="logException" class="onlyfun.caterpillar.aop.LogExceptionAdvice"/>
<bean id="helloSpeaker" class="onlyfun.caterpillar.aop.HelloSpeaker"/>
<bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="onlyfun.caterpillar.aop.IHello"/>
<property name="target" ref="helloSpeaker"/>
<property name="interceptorNames">
<list>
<value>logBeforeAdvice</value>
<value>logAfterAdvice</value>
<value>logInterceptor</value>
<value>logException</value>
</list>
</property>
</bean>
</beans>
<bean id="logAfterAdvice" class="onlyfun.caterpillar.aop.LogAfterAdvice"/>
<bean id="logInterceptor" class="onlyfun.caterpillar.aop.LogAroundAdvice"/>
<bean id="logException" class="onlyfun.caterpillar.aop.LogExceptionAdvice"/>
<bean id="helloSpeaker" class="onlyfun.caterpillar.aop.HelloSpeaker"/>
<bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="onlyfun.caterpillar.aop.IHello"/>
<property name="target" ref="helloSpeaker"/>
<property name="interceptorNames">
<list>
<value>logBeforeAdvice</value>
<value>logAfterAdvice</value>
<value>logInterceptor</value>
<value>logException</value>
</list>
</property>
</bean>
</beans>
测试一下,用ApplicationContext提取配置文件,获得代理对象并转化为IHello接口,从接口调用方法,第一次传递非空串,第二次传递空串引发异常:
public class MainTest ...{
public static void main(String[] args) ...{
ApplicationContext context = new ClassPathXmlApplicationContext(
"beanaop-config.xml");
IHello helloProxy = (IHello) context.getBean("helloProxy");
try ...{
helloProxy.say_hello("Tommy");
helloProxy.say_hello(null);
} catch (Throwable t) ...{
System.out.println(t);
}
}
}
public static void main(String[] args) ...{
ApplicationContext context = new ClassPathXmlApplicationContext(
"beanaop-config.xml");
IHello helloProxy = (IHello) context.getBean("helloProxy");
try ...{
helloProxy.say_hello("Tommy");
helloProxy.say_hello(null);
} catch (Throwable t) ...{
System.out.println(t);
}
}
}
结果如下:
Before say_hello starts
In method-intercept, before method
hello,Tommy!
In method-intercept, Method say_hello end.
method say_hello ends,res...succeed
====================
Before say_hello starts
In method-intercept, before method
In ThrowsAdvice:Exceptionjava.lang.NullPointerException: The arg is null...: occurs at method say_hello
In method-intercept, Method say_hello end.
in main test:java.lang.NullPointerException: The arg is null...
一切如常。搞清了基本概念,后面或有变化不外如是。
- 我和春天有个约会(四)
- 我和春天有个约会
- 我和春天有个约会(一)
- 我和春天有个约会(二)
- 我和春天有个约会(三)
- 和春天有个约会
- 参加不愿让你一个人之我和春天有个约会的看法
- 我和.NET有个约会!!
- 我和英语有个约会
- 我和python有个约会
- 我和明星有个“约会”
- 我和书、有个约会。
- 我和气功有个约会
- 我和node.js有个约会
- 我和未来有个约会
- 我和夏天有个约会 2017.0711
- 我和奥运有个约会:我的奥运畅想
- 我和僵尸有个约会·僵尸游戏精选
- 数据仓库设计的七个步骤
- ASP.Net中利用CSS实现多界面两法
- 静思语(一)
- A way to get filename from batch
- 路,自己选的,有主动和被动之别
- 我和春天有个约会(四)
- Visual Studio 2005 部署3
- 静思语(二)
- sumba 在 ubuntu linux 下的重启操作
- 成年人必看的5个故事
- 还爱着你心中曾经那朵红玫瑰吗?
- 传递一个指针进去用(指针不能被修改)*p;
- 读《漂亮女上司》有感
- 调用API弹出打印机属性对话框