- 论坛徽章:
- 0
|
一,从代理机制初探AOP
1,使用静态代理
#代理对象和被代理对象必须实现共同的接口
package com.biaoflying;
public interface IHello {
public void hello(String name);
}
#代理对象HelloProxy
package com.biaoflying;
import java.util.logging.*;
public class HelloProxy implements IHello {
private IHello helloObject;
private Logger logger=
Logger.getLogger(this.getClass().getName());
public HelloProxy(IHello helloObject){
this.helloObject=helloObject;
}
public void hello(String name){
log("hello method starts....");
helloObject.hello(name);
log("hello method ends....");
}
private void log(String msg){
logger.log(Level.INFO,msg);
}
}
#HelloSpeaker被代理对象
package com.biaoflying;
public class HelloSpeaker implements IHello {
public void hello(String name){
System.out.println("Hello "+name);
}
}
#主程序
package com.biaoflying;
public class ProxyDemo {
public static void main(String[] args){
HelloProxy proxy=
new HelloProxy(new HelloSpeaker());
proxy.hello("biaoflying");
}
}
#执行ProxyDemo的输出
信息: hello method starts....Hello biaoflying2008-3-21 9:05:40 com.biaoflying.HelloProxy log信息: hello method ends....
TIP:使用静态代理,代理对象和被代理对象必须实现共同的接口。本质上就是由代理对象呼叫被代理对象并执行相关的逻辑。同时可以看到,静态代理在程序规模稍大时就无法胜任了。
-----------------------------------------------------------------------------------
2,动态代理
去掉HelloProxy.java,编写以下的LogHandler.java文件。
package com.biaoflying;
import java.util.logging.*;
import java.lang.reflect.*;
public class LogHandler implements InvocationHandler{
private Logger logger=
Logger.getLogger(this.getClass().getName());
private Object delegate;
public Object bind(Object delegate){
this.delegate=delegate;
return Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy,Method method,
Object[] args)throws Throwable{
Object result = null;
try{
log("method starts..."+method);
result=method.invoke(delegate,args);
logger.log(Level.INFO,"method ends..."+method);
}catch(Exception e){
log(e.toString());
}
return result;
}
private void log(String msg){
logger.log(Level.INFO,msg);
}
}
#主程序
package com.biaoflying;
public class ProxyDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LogHandler logHandler=new LogHandler();
IHello helloProxy=
(IHello)logHandler.bind(new HelloSpeaker());
helloProxy.hello("biaoflying");
}
}
TIP:动态代理的执行流程是Proxy.newProxyInstance(..,..,this)方法返回一个代理对象,该代理对象每次执行相关的方法时都会委托给this.invoke方法。
-----------------------------------------------------------------------------------
二,Advices
由于织入Targets的时机不同,Advices被分为以下几种:Before advice,After advice,Around advice,Throw advice。
#MethodBeforeAdvice接口
package org.springframework.aop;
public interface MethodBeforeAdvice extends BeforeAdvice{
void before(Method method,Object[] args,Object target)
throws Throwable;
}
具体的例子,IHello接口和HelloSpeaker.java如上
package com.biaoflying;
import java.lang.reflect.Method;
import java.util.logging.*;
import org.springframework.aop.MethodBeforeAdvice;
public class LogBeforeAdvice
implements MethodBeforeAdvice{
private Logger logger=
Logger.getLogger(this.getClass().getName());
public void before(Method method,Object[] args,
Object target)throws Throwable{
logger.log(Level.INFO,"Method starts..."+method);
}
}
package com.biaoflying;
import org.springframework.context.*;
import org.springframework.context.support.*;
public class SpringAOPDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context=
new FileSystemXmlApplicationContext(
"beans-config.xml");
IHello helloProxy=(IHello)context.getBean(
"helloProxy");
helloProxy.hello("biaoflying");
}
}
com.biaoflying.IHello
logBeforeAdvice
执行SpringAOPDemo.java会在hello方法执行之前输出log消息。
另外对于After advice,Around advice是类似的。
-----------------------------------------------------------------------------------
三,Throw Advice
表示在目标对象调用方法发生异常时添加一个Aspect。
package com.biaoflying;
public interface IHello {
public void hello(String name)throws Throwable;
}
package com.biaoflying;
public class HelloSpeaker implements IHello {
public void hello(String name)throws Throwable{
System.out.println("Hello "+name);
throw new Exception("发生异常...");
}
}
package com.biaoflying;
import java.lang.reflect.Method;
import java.util.logging.*;
import org.springframework.aop.ThrowsAdvice;
public class SomeThrowAdvice implements ThrowsAdvice{
private Logger logger=
Logger.getLogger(this.getClass().getName());
public void afterThrowing(Method method,Object[] args,Object target,Throwable subclass){
logger.log(Level.INFO,
"Logging that a "+subclass+
"Exception was thrown in "+method);
}
}
package com.biaoflying;
import org.springframework.context.ApplicationContext;
import org.springframework.
context.support.FileSystemXmlApplicationContext;
public class SpringAOPDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context=
new FileSystemXmlApplicationContext(
"beans-config.xml");
IHello helloProxy=
(IHello)context.getBean("helloProxy");
try{
helloProxy.hello("biaoflying");
}catch(Throwable throwable){
System.err.println(throwable);
}
}
}
com.biaoflying.IHello
someThrowAdvice
四,更为细化的AOP programming。
通过定义Ponitcut来实现更为细化的AOP编程,如可以指定在Target的某个方法执行时加入advice。
package com.biaoflying;
public interface IHello {
public void helloNewbie(String name);
public void helloMaster(String name);
}
package com.biaoflying;
public class HelloSpeaker implements IHello {
public void helloNewbie(String name){
System.out.println("Hello "+name+" newbie");
}
public void helloMaster(String name){
System.out.println("Hello "+name+" will be master");
}
}
package com.biaoflying;
import java.lang.reflect.Method;
import java.util.logging.*;
import org.springframework.aop.MethodBeforeAdvice;
public class LogBeforeAdvice
implements MethodBeforeAdvice{
private Logger logger=
Logger.getLogger(this.getClass().getName());
public void before(Method method,Object[] args,
Object target)throws Throwable{
logger.log(Level.INFO,"Method starts..."+method);
}
}
package com.biaoflying;
import org.springframework.context.ApplicationContext;
import org.springframework.
context.support.FileSystemXmlApplicationContext;
public class SpringAOPDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context=
new FileSystemXmlApplicationContext(
"beans-config1.xml");
IHello helloProxy=
(IHello)context.getBean("helloProxy");
helloProxy.helloNewbie("abio");
helloProxy.helloMaster("biaoflying");
}
}
hello*
com.biaoflying.IHello
helloAdvisor
另外一个静态PointcutAdvisor为RegexpMethodPointcutAdvisor,更改以上的配置:
.*hello.*
com.biaoflying.IHello
helloAdvisor
两者都可以得到一下的输出:
信息: Method starts...public abstract void com.biaoflying.IHello.helloNewbie(java.lang.String)2008-3-22 18:38:22 com.biaoflying.LogBeforeAdvice before信息: Method starts...public abstract void com.biaoflying.IHello.helloMaster(java.lang.String)
Hello abio newbie
Hello biaoflying will be master
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/63463/showart_502012.html |
|