由spring 的aop 想到java 的动态代理
概念
另外,它的实现原理其实就是Java的动态代理,但是jdk的动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前 需要实现接口InvokeHandler来处理,所以,spring中的aop使用了cglib这个库来实现,而 cglib使用了asm这个直接操纵字节码的框架,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理,所以可以做到不实现接口的情况下,完成动态代理。
ioc 控制反转编程,其实就是依赖注入,在程序中不出现new关键字,直接通过接口命名引用,然后通过某种方式,把接口的某个具体实现 类的实例,注入到引用中,从而实现了与接口具体实现类的松耦合。
结论为: Spring AOP中,当拦截对象实现了接口时,生成方式是用JDK的Proxy类。当没有实现任何接口时用的是GCLIB开源项目生成的拦截类的子类.
aop运用场景:事务,日志,监控等。
它的作用:
1.Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
2.可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
3.解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。
代理概念:
静态代理类:
动态代理
下面写个例子
有4个类结合
接口类, 想象为service
public interface Subject {
public void doSomething();
}
实现类 , 想象为service的实现层
public class RealSubject implements Subject {
public void doSomething(){
System.out.println( "call doSomething()" );
}
}
public class ProxyHandler implements InvocationHandler{
private Object tar; //绑定委托对象,并返回代理类
public Object bind(Object tar) {
this.tar = tar;
//绑定该类实现的所有接口,取得代理类
// 方法参数说明:代理类、代理类实现的接口列表、代理类的处理器
// 关联代理类、代理类中接口方法、处理器,当代理类中接口方法被调用时,会自动分发到处理器的invoke方法
// 如果代理类没有实现指定接口列表,会抛出非法参数异常
return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
tar.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy , Method method , Object[] args)throws Throwable {
Object result = null;
//这里就可以进行所谓的AOP编程了
//在调用具体函数方法前,执行功能处理
result = method.invoke(tar,args);
//在调用具体函数方法后,执行功能处理
return result;
}
}
测试类
public class TestProxy {
public static void main(String args[])
{
ProxyHandler proxy = new ProxyHandler();
//绑定该类实现的所有接口
Subject sub = (Subject) proxy.bind(new RealSubject());
sub.doSomething();
}
}
看完代码
主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情
静态代理:
下面代码解释:
TestService类是代理类,TestServiceImpl类是委托类,这两个类都实现了TestService 接口。其中TestServiceImpl类是TestService 接口的真正实现者,而TestServiceProxy类是通过调用TestServiceImpl类的相关方法来提供特定服务的。TestServiceProxy类的say()方法会调用被代理的TestServiceImpl对象的say()方法,并且在方法调用前后都会执行一些简单的打印操作。
TestService.java
public interface TestService{
}
TestServiceImpl.java
public class TestServiceImpl implements TestService{
public String say(String msg){
TestServiceProxy.java
public class TestServiceProxy implements TestService{
}
这里TestServiceProxy 定义出来不是多余,后来随着业务庞大,你就会知道,实现proxy类对真实类的封装对于粒度的控制有着重要的意义。但是静态代理这个模式本身有个大问题,如果类方法数量越来越多的时候,代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题。
ClientTest.java
package proxy;
public class ClientTest{
}
运行ClientTest类,打印结果如下:
before calling say()
say-->hello,welcome~~~
after calling say()
TestServiceProxy类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。
代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。
理解浅显,供自己阅读,多看看源码能理解更多。
其他相关文章连接:
http://blog.csdn.net/intlgj/article/details/5671927
http://www.zhihu.com/question/20794107/answer/23330381