我们来使用代理实现下简单的日志功能。
我们要在调用一个接口方法的时候给他记录日志的功能。
静态代理:
静态代理关键在代理对象和目标对象实现共同接口,并且代理对象持有目标对象的引用。
接口:
public interface DemoService {
void doSomeThing(String name);
}
实现类:
class DemoServiceImpl implements DemoService {
@Override
public void doSomeThing(String name) {
System.out.println("doing things"+name);
}
}
静态代理类
public class ProxyDemoServiceImpl implements DemoService {
private DemoService demoService;
private ProxyDemoServiceImpl(DemoService demoService){
super();
this.demoService=demoService;
}
@Override
public void doSomeThing(String name) {
//日志增强
System.out.println("log begin");
demoService.doSomeThing(name);
System.out.println("long end");
}
//main
public static void main(String[] args) {
//原实现类
DemoService service = new DemoServiceImpl();
//静态代理对象
service = new ProxyDemoServiceImpl(service);
service.doSomeThing("单边李");
}
}
//结果
log begin
doing things单边李
long end
静态代理的问题:项目中接口众多,方法也更多。这样一个一个增加,太麻烦了。
动态代理:
接口:
public interface DemoService {
void doSomeThing(String name);
}
实现类:
public class DoTaiDemoServiceImpl implements DemoService {
@Override
public void doSomeThing(String name) {
System.out.println("doing things"+name);
}
}
关键的动态代理接口
在java动态代理机制中,有两个重要的类或接口:InvocationHandler(interface),Proxy(class)。这个接口和类是实现动态代理所必需用到的。
public class DoTaiDemoService implements InvocationHandler {
//目标对象
private Object target;
public Object bind(Object object){
//传入目标对象
this.target=object;
//生成动态代理对象
Object obj = Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
return obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
System.out.println("method:"+method);
System.out.println("args:"+ Arrays.toString(args));
//增强,日志
System.out.println("log:begin");
try {
//反射,动态调用方法
result= method.invoke(this.target,args);
}catch (Exception e){
throw e;
}
System.out.println("log:end");
return result;
}
public static void main(String[] args) {
//动态代理对象调用目标对象
//动态代理对象调用目标方法的时候,会执行代理对象的invoke方法,增加日志和try,并回调目标对象的方法
DemoService service = (DemoService)new DoTaiDemoService().bind(new DoTaiDemoServiceImpl());
service.doSomeThing("单边李");
}
}
//结果:
args:[单边李]
log:begin
doing things单边李
log:end
和静态代理的区别:不用为每个接口创建代理类,只需要动态代理对象的bind方法,就可以获得织入增强后的对象。