Java 动态代理学习理解

<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);
	}
	

}


然后该做什么了 该创建我们的动态代理类了吧 怎么创建呢我们先写个main方法在main方法中 用proxy类的静态方法来创建

</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");
	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值