Spring Aop入门.docx
《Spring Aop入门.docx》由会员分享,可在线阅读,更多相关《Spring Aop入门.docx(15页珍藏版)》请在冰豆网上搜索。
![Spring Aop入门.docx](https://file1.bdocx.com/fileroot1/2022-12/12/62c0024e-0627-4f73-8d8d-7e33e4ff2359/62c0024e-0627-4f73-8d8d-7e33e4ff23591.gif)
SpringAop入门
Spring -Aop入门
AOP全名Aspect-orientedprogramming。
Spring framework是很有前途的AOP技术。
作为一种非侵略性的,轻型的AOPframework,你无需使用预编译器或其他的元标签,便可以在Java程序中使用它。
这意味着开发团队里只需一人要对付AOPframework,其他人还是像往常一样编程。
关键性概念:
1) Advice 是代码的具体实现,例如一个实现日志记录的代码。
2) Pointcut 是在将Advice 插入到程序的条件。
3) advisor是把pointcut和advice的组合在一起装配器。
图例:
你的程序可能如上,现在要在三个流程上同时加入日志控制和权限控制,如下:
你的程序可能如上,现在要在三个流程上同时加入日志控制和权限控制,如下:
其中拿日志为例,日志控制和流程之间的穿插点处叫做连接点(Joinpoint),而Advice就是我们日志处理的具体代码,Pointcut就是定义一个规则,对三个和业务有关的连接点进行过滤和匹配(例如我们对于业务1不做日志处理)。
Advisor就是将符合的规则的剩下的两个连接点和具体的日志记录代码组合在一起。
三. Spring-Aop 前置通知、后置通知、环绕通知、异常通知实现
我以Spring InAction 提供的例子进行二次改造,完成我们自己的流程。
业务流程很简单,顾客到商店买东西,店员根据顾客的需要给于顾客提供服务。
实现方法前插入,方法后插入,环绕,异常四种。
代码:
建立一个用户类;
publicclassCustomer {
privateStringname="悠~游!
";
publicStringgetName(){
returnname;
}
}
三个产品
publicclassCheese{
publicStringtoString(){
return"奶酪!
";
}
}
publicclassPepper{
publicStringtoString(){
return"胡椒粉!
";
}
}
publicclassSquish{
publicStringtoString(){
return"果酱!
";
}
}
建立一个接口;
publicinterfaceKwikEMart{
SquishbuySquish(Customercustomer)throwsKwikEMartException;
PepperbuyPepper(Customercustomer)throwsKwikEMartException;
CheesebuyCheese(Customercustomer)throwsKwikEMartException;
}
实现这个接口,我们实现三个方法,买奶酪,买胡椒粉,买果酱;
publicclassApuKwikEMartimplementsKwikEMart{
privatebooleancheeseIsEmpty=false;
privatebooleanpepperIsEmpty=false;
privatebooleansquishIsEmpty=false;
publicCheesebuyCheese(Customercustomer)throwsNoMoreCheeseException{
if(cheeseIsEmpty){
thrownewNoMoreCheeseException();
}
Cheeses=newCheese();
System.out.println("--我想买:
"+s);
returns;
}
publicPepperbuyPepper(Customercustomer)throwsNoMorePepperException{
if(pepperIsEmpty){
thrownewNoMorePepperException();
}
Peppers=newPepper();
System.out.println("--我想买:
"+s);
returns;
}
publicSquishbuySquish(Customercustomer)throwsNoMoreSquishException{
if(squishIsEmpty){
thrownewNoMoreSquishException();
}
Squishs=newSquish();
System.out.println("--我想买:
"+s);
returns;
}
publicvoidsetCheeseIsEmpty(booleancheeseIsEmpty){
this.cheeseIsEmpty=cheeseIsEmpty;
}
publicvoidsetPepperIsEmpty(booleanpepperIsEmpty){
this.pepperIsEmpty=pepperIsEmpty;
}
publicvoidsetSquishIsEmpty(booleansquishIsEmpty){
this.squishIsEmpty=squishIsEmpty;
}
}
环绕通知的实现,必须实现invoke方法,通过调用invoke.proceed()手工调用对象方法:
publicclassOnePerCustomerInterceptorimplementsMethodInterceptor{
privateSetcustomers=newHashSet();
publicObjectinvoke(MethodInvocationinvoke)throwsThrowable{
Customercustomer=(Customer)invoke.getArguments()[0];
if(customers.contains(customer)){
thrownewKwikEMartException("Onepercustomer.");
}
System.out.println("店员:
"+customer.getName()+",CanIhelpyou?
");
Objectsquishee=invoke.proceed();//手工调用对象方法;
System.out.println("店员:
OK!
"+customer.getName()+".giveyou!
");
customers.add(squishee);
returnsquishee;
}
}
前置通知的实现;
publicclassWelcomeAdviceimplementsMethodBeforeAdvice{
publicvoidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{
Customercustomer=(Customer)args[0];
System.out.println("店员:
:
Hello"+customer.getName()+".Howareyoudoing?
");
}
}
publicclassCustomer {
privateStringname="悠~游!
";
publicStringgetName(){
returnname;
}
}
后置通知实现;
publicclassThankYouAdviceimplementsAfterReturningAdvice{
publicvoidafterReturning(ObjectreturnValue,Methodmethod,Object[]args,Objecttarget)throwsThrowable{
Customercustomer=(Customer)args[0];
System.out.println("店员:
Thankyou"+customer.getName()+".Comeagain!
");
}
}
系统异常处理通知实现;
publicclassKwikEmartExceptionAdviceimplementsThrowsAdvice{
publicvoidafterThrowing(NoMoreSquishExceptione){
System.out.println("系统:
NoMoreSquisheesException异常截获了:
"+e.getMessage());
}
publicvoidafterThrowing(NoMoreCheeseExceptione){
System.out.println("系统:
NoMoreCheeseException异常截获了:
"+e.getMessage());
}
publicvoidafterThrowing(NoMorePepperExceptione){
System.out.println("系统:
NoMorePepperException异常截获了:
"+e.getMessage());
}
}
自定义的异常接口;
publicclassKwikEMartExceptionextendsException{
privatestaticfinallongserialVersionUID=-3962577696326432053L;
StringretValue="KwikEMartException 异常!
";
publicKwikEMartException(Stringname){
retValue=name;
}
publicKwikEMartException(){
}
publicStringgetMessage(){
returnretValue;
}
}
没有更多的奶酪异常;
publicclassNoMoreCheeseExceptionextendsKwikEMartException{
privatestaticfinallongserialVersionUID=-3961123496322432053L;
StringretValue="NoMoreCheeseException 异常!
";
publicNoMoreCheeseException(){
super();
}
publicNoMoreCheeseException(Stringname){
super(name);
}
publicStringgetMessage(){
returnretValue;
}
}
没有更多的胡椒粉异常;
publicclassNoMorePepperExceptionextendsKwikEMartException{
privatestaticfinallongserialVersionUID=-3961234696322432053L;
StringretValue="NoMorePepperException 异常!
";
publicNoMorePepperException(){
super();
}
publicNoMorePepperException(Stringname){
super(name);
}
publicStringgetMessage(){
returnretValue;
}
}
没有更多的果酱异常;
publicclassNoMoreSquishExceptionextendsKwikEMartException{
privatestaticfinallongserialVersionUID=-3121234696322432053L;
StringretValue="NoMoreSquishException 异常!
";
publicNoMoreSquishException(){
super();
}
publicNoMoreSquishException(Stringname){
super(name);
}
publicStringgetMessage(){
returnretValue;
}
}
运行实例类;
publicclassRunDemo{
publicstaticvoidkwikEMart(){
ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("demo/kwikemart.xml");
//如果你想通过类来引用这个的话,就要用到CGLIB.jar了,同时在代理工厂里面设置:
//
KwikEMartakem=(KwikEMart)context.getBean("kwikEMart");
try{
akem.buySquish(newCustomer());
akem.buyPepper(newCustomer());
akem.buyCheese(newCustomer());
}catch(KwikEMartExceptione){
//异常已经被截获了,不信你看控制台!
~;
}
}
publicstaticvoidmain(String[]args){
kwikEMart();
}
}
Xml文件配置:
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:
//www.springframework.org/dtd/spring-beans.dtd">
--
把这里注释去掉的话,程序调用的时候测试异常通知;
true
true
true
-->
-- 方法调用前通知 -->
-- 方法调用后通知-->
-- 环绕调用通知 -->
-- 异常调用通知 -->
welcomeAdvice
thankYouAdvice
onePerCustomerInterceptor
kwikEmartExceptionAdvice
这个例子东西很多,不过每个类的代码都不大。
如果你对org.springframework.aop.framework.ProxyFactoryBean不是很了解的话可以看我下篇尾处的介绍。
读清楚之后,我们运行RunDemo类,查看控制台结果,如下:
店员:
:
Hello悠~游!
.Howareyoudoing?
店员:
悠~游!
CanIhelpyou?
--我想买:
果酱!
店员:
OK!
悠~游!
.giveyou!
店员:
Thankyou悠~游!
.Comeagain!
店员:
:
Hello悠~游!
.Howareyoudoing?
店员:
悠~游!
CanIhelpyou?
--我想买:
胡椒粉!
店员:
OK!
悠~游!
.giveyou!
店员:
Thankyou悠~游!
.Comeagain!
店员:
:
Hello悠~游!
.Howareyoudoing?
店员:
悠~游!
CanIhelpyou?
--我想买:
奶酪!
店员:
OK!
悠~游!
.giveyou!
店员:
Thankyou悠~游!
.Comeagain!
我们将kwikEMartTarget里面的