<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">一直对AOP理解停留在字面解释理解层面,这两天看了些资料也自己写了例子把学习理解的内容记录下来,方便记忆也加深理解</span>
AOP就是面向切面编程 其实现原理就是动态代理和java反射,
InvocationHandler动态代理调用管理接口 是动态代理最核心的部分 该接口在java.lang.reflect包下
官方文档 InvocationHandler是代理实例的调用处理程序实现接口
什么意思呢
也就是我们创建一个动态代理类动态代理类是实现了我们当前类的接口的 在我们用动态代理类实例调用接口方法的时候 动态代理类实例会自动调用 调用处理程序接口里的invoke方法 通过这个方法来完成对方法的调用实现。 这里唯有代码能够表明清楚
我们先创建一个含有一个方法的接口
public interface IHello {
public void sayHello(String name);
}
然后我们再创建一个实现了该接口的类
public class Hello implements IHello {
public void sayHello(String name) {
System.out.println("hello:"+name);
}
}
</pre><p></p><p class="p1"></p><pre name="code" class="java">public static void main(String[] args) {
<p class="p1">Proxy.newProxyInstance(<span class="s1">loader</span>, <span class="s1">interfaces</span>, <span class="s1">h);</span></p>
}
proxy.newProxyInstance 鼠标放到方法上可以看到上面的一段方法说明
该方法有三个参数 类加载器 ,接口 ,动态代理调用处理器
第一个和第二个分别对应我们上面创建的接口和实现类很好理解,第三个也是我们最核心最重要的一个动态代理调用处理器
还记得我们上面提到 reflect 下面的invocationHandler接口吗
对啦 第三个参数就是实现了invocationHandler接口的类的实例,那我们就来写个类来实现invocationHandler这个接口吧。
public class DynamicDelegate implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}
</pre>这时候我们在main中的proxy.newProxyInstance 三个参数就都具备了上代码<pre name="code" class="java">public static void main(String[] args) {
DynamicDelegate dyn = new DynamicDelegate();
IHello hello = (IHello) Proxy.newProxyInstance(Hello.class.getClassLoader(), Hello.class.getInterfaces(), dyn);
hello.sayHello("Jane");
hello.sayBye("Many");
}
这时候我们这个动态代理步骤就写完了 各位看官可以在自己eclipse里执行下main看看
这时候你会发现 程序没有报错但是同时也并没有按照我们预期的打印出来 “Jane”和“Many”对吧 这时候你就疑惑了 哎 没有报错但是为什么没有输出呢
这个问题就出来这里
public class DynamicDelegate implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//问题就在这里
return null;
}
}
代理类实例调用接口方法会自动调用 invoke方法 我们的方法中返回null 所以在控制台中就没有任何输出了,
我们来分析下invoke这个方法,这个方法也有三个参数 代理类实例,调用的方法,方法参数
如果想让我们的控制台输出内容 就需要用method.invoke 来执行对象的方法 invoke有两个参数 类的对象,方法参数
我们是对 Hello这个类进行的代理 第一个参数也就是 hello这个类的实例
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = null;
result = method.invoke(new Hello(), args);
return result;
}
到这一步在执行我们的程序就能在控制台成功的看到内容了
到这里就完了吗,no 这怎么能体现出代理的意义呢 一切才刚刚开始
我们可以在方法执行之前 先做一些其他的东西
比如在方法执行之前输出一些我们自己的东西
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = null;
<span style="white-space:pre"> </span>System.out.println("this is test");
result = method.invoke(new Hello(), args);
return result;
}
我们在我们的接口中添加一个新的方法 sayBye 同样实现类也是要实现这个方法
public interface IHello {
public void sayHello(String name);
public void sayBye(String name);
}
public class Hello implements IHello {
public void sayHello(String name) {
System.out.println("hello:"+name);
}
public void sayBye(String name) {
System.out.println("bye my friend "+name);
}
}
才是再执行下看下输出结果
我们之前加的this is test 再每个方法执行之前都会打印一遍 但是我不想这样 我只想在 sayHello的时候才执行这句 那怎么办
还是用到java 反射里边的方法名获取 method.getName 用这个来获取当前执行的方法名称 然后进行过滤
话不多说上代码
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = null;
if (method.getName().equals("sayHello")) {
System.out.println("this is test");
result = method.invoke(new Hello(), args);
}else {
result = method.invoke(new Hello(), args);
}
return result;
}
现在我们再来执行一下程序。
已经按照我们预期的执行了
到这我的整个动态代理例子也就写完了 ,第一次用写的方式把学习的过程记录下来,可能有很多地方表述的不够正确严谨,也请路过的大牛多多指正。
最后贴上我优化后的代码例子
<p class="p1"><span class="s1">public</span> <span class="s1">class</span> DynamicDelegate <span class="s1">implements</span> InvocationHandler {</p><p class="p2">
</p><p class="p1"><span> </span><span class="s1">private</span> Object <span class="s2">delegate</span>;</p><p class="p2"><span> </span></p><p class="p1"><span> </span><span class="s1">public</span> Object bind(Object delegate){</p><p class="p1"><span> </span><span> </span><span class="s1">this</span>.<span class="s2">delegate</span> = delegate;</p><p class="p1"><span> </span><span> </span><span class="s1">return</span> Proxy.newProxyInstance(<span class="s1">this</span>.<span class="s2">delegate</span>.getClass().getClassLoader(), <span class="s1">this</span>.<span class="s2">delegate</span>.getClass().getInterfaces(), <span class="s1">this</span>);</p><p class="p1"><span> </span>}</p><p class="p2"><span> </span></p><p class="p1"><span> </span><span class="s1">public</span> Object invoke(Object proxy, Method method, Object[] args)<span class="s1">throws</span> Throwable {</p><p class="p1"><span> </span><span> </span>Object result = <span class="s1">null</span>;</p><p class="p2"><span> </span><span> </span></p><p class="p1"><span> </span><span> </span><span class="s1">if</span> (method.getName().equals(<span class="s3">"sayHello"</span>)) {</p><p class="p1"><span> </span><span> </span><span> </span>System.<span class="s2">out</span>.println(<span class="s3">"this is test"</span>);</p><p class="p1"><span> </span><span> </span><span> </span>result = method.invoke(<span class="s1">this</span>.<span class="s2">delegate</span>, args);</p><p class="p2"><span> </span><span> </span><span> </span></p><p class="p1"><span> </span><span> </span>}<span class="s1">else</span> {</p><p class="p1"><span> </span><span> </span><span> </span>result = method.invoke(<span class="s1">this</span>.<span class="s2">delegate</span>, args);</p><p class="p1"><span> </span><span> </span>}</p><p class="p2">
</p><p class="p1"><span> </span><span> </span><span class="s1">return</span> result;</p><p class="p1"><span> </span>}</p><p class="p1">}</p>
public static void main(String[] args) {
IHello hello = (IHello) new DynamicDelegate().bind(new Hello());
// DynamicDelegate dyn = new DynamicDelegate();
// IHello hello = (IHello) Proxy.newProxyInstance(Hello.class.getClassLoader(), Hello.class.getInterfaces(), dyn);
hello.sayHello("Jane");
hello.sayBye("Many");
}