其实学一项技术,我们要明确几样东西,一是需要去了解这项技术能干嘛,二是我拿这项技术可以拿来帮我解决什么样的需求,还有就是这项技术的优缺点格式什么,我该在什么样的场合去用他们,本文围绕这几个方面来展开述说。
首先说一下动态代理能拿来干嘛,假如说我们今天下班了想直接就回家吃饭,这一行程我们已经决定好了,可是下班的时候走在路上临时决定想去买点好吃的干粮带回去,想一下我们在程序中,我们已经写好了代码,在原本代码不变的情况下,我们应该怎样去做呢。
注意: 代理必须需要有接口
第一种方法:我们可以用静态代理。
接口:
public interface AbsTarget {
public void eat();
}
这就是我们下班回假吃饭的一个接口,
我们原来的决定下班回假直接吃饭:我们新建一个类去实现这个接口:
public class Target implements AbsTarget {
public void eat() {
System.out.println("eating");
}
}
好,假如说这就是我们正常的逻辑代码:
但是现在我们想在吃饭前加一点逻辑代码,假如以后你在实际工作中你的leader想让你在某个方法前打印日志,想想这时候你该怎么做你这时候可能会想到,我会这么做:
public class Target implements AbsTarget {
public void eat() {
System.out.println("log...");
System.out.println("eating");
}
}
可能你会这样想,这样不是很好?简单方便快捷,这种低级做法不觉得自己的代码很low吗,我们用一点高大上的做法,其实上在实际在实际的项目中的实际是尽量不要去随意改变业务代码,我们可以去重新定义一个类,去实现这个接口。
public class AbsTargetImp implements AbsTarget {
private AbsTarget t;
public AbsTargetImp(){
t = new Target();
}
@Override
public void eat() {
System.out.println("hello");
t.eat();
//也可以在后面添加一些逻辑代码
}
}
这里写的并不·严谨,主要是方便大家理解,这就是静态代理,这时候我们想想如果还要再上面加一些逻辑,或者说还有其他的类需要添加逻辑,那是不是带来一个很大的问题,类越来越多。这时候我们就来介绍一下jdk的动态代理,它很完美的解决了这个问题。
首先我来给大家介绍一下怎么使用。
我们还是跟开头一样,以吃饭为例,再前后增加逻辑。
接口:
public interface eat {
public void eat();
}
正常的逻辑实现:
public class eatImp implements eat {
@Override
public void eat() {
System.out.println("eating");
}
}
还是老样子,我们想要在正常的逻辑前后增加逻辑代码:
public class DynamicProxy2 implements InvocationHandler{
private Object obj;
public DynamicProxy2(Object obj) { //构造方法,这里用到是Object超类,这是真正的正常逻辑的类
// TODO Auto-generated constructor stub
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
before(); //在正常逻辑前面添加的功能
Object result = method.invoke(obj, args); //利用到的反射
after(); //在正常逻辑后面添加的功能
return result;
}
private void after() {
// TODO Auto-generated method stub
System.out.println("饭后");
}
private void before() {
// TODO Auto-generated method stub
System.out.println("饭前");
}
@SuppressWarnings("unchecked")
public<T> T GetProxy() {
return (T)Proxy.newProxyInstance(
obj.getClass().getClassLoader(), //类加载器
obj.getClass().getInterfaces(), //获取接口
this);
}
}
这样我们想在正常的逻辑代码的前后添加逻辑就不用再去新建很多类,只需要在代理类里面修改逻辑即可,主函数的调用:
public class Test {
public static void main(String[] args) throws IOException {
eat e = new eatImp();
DynamicProxy2 dp = new DynamicProxy2(e);
//DynamicImp.newProxyInstance(new AbsTargetImp(e));
eat e1 = dp.GetProxy();
e1.eat();
}
}