---------------------- android培训、java培训、期待与您交流! ----------------------
对动态代理的理解
动态代理就是拦截对被代理对象的请求
打个比方:一个明星有唱歌和跳舞两个方法,这个明星还有一个经纪人,这个经纪人就是代理,明星就是被代理,你想找这个明星唱歌跳舞,先要找这个经纪人,这个经纪人就是拦截向明星也就是被代理对象的请求,同时这个经纪人也就是代理也具备和被代理对象一样的方法唱歌和跳舞
用动态代理增强对象功能就是拦截对被代理对象的请求,把被代理对象增强后在返回
详解动态代理
1、jdk的动态代理
1、目标接口 (就是被代理类的接口)
2、目标类 (就是被代理类)
3、代理类
4、拦截器
5、代理对象和目标对象实现了共同的接口
2、cglib的动态代理
1、目标类
2、代理类
3、拦截器
4、目标类是代理类的父类
public interface B {
public void show();
public String run(int x);
}
public class A implements B{
public void show(){
System.out.println("A的show");
}
public String run(int x){
return "A的run"+x;
}
}
//创建cglib式的动态代理的拦截器
public class CglibProxy implements MethodInterceptor { //cglib动态代理,不需要被代理类有接口,需要导入cglib的jar包,他采用的是代理类继承被代理类的方式
private Object o; //被代理对象
public CglibProxy(Object o){
this.o=o;
}
//产生代理对象
public Object createProxyObject(){
//这是模板代码,直接抄就ok了
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.o.getClass()); //给代理类设置父类,父类就是被代理类
enhancer.setCallback(this); //设置拦截器 回调接口
return enhancer.create(); //产生代理对象
}
@Override
public Object intercept(Object arg0, Method method, Object[] arg2,
MethodProxy arg3) throws Throwable {
if(method.getName().equals("run")){
System.out.println("A类的run方法增强了");
method.invoke(o, arg2); //将被代理对象传进去。args是参数
}
if(method.getName().equals("show")){
System.out.println("A类的show方法增强了");
return method.invoke(o, arg2);
}
return null;
}
}
//创建cglib式的动态代理的代理对象
class CreateCglibProxy{
public static void main(String[] args) {
A o = new A();
CglibProxy interceptor = new CglibProxy(o);
A a = (A)interceptor.createProxyObject(); //被代理类没有接口,所以这里用A被代理的父类指向代理对象
System.out.println(a.run(1));
a.show();
}
}
//创建拦截器
public class JDKProxy implements InvocationHandler {//拦截器,实现InvocationHandler接口
private Object o; //被代理对象,采用了object,也就是说所有的对象都能被代理
public JDKProxy(Object o){
this.o=o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("run")){
System.out.println("A类的run方法增强了");
return method.invoke(o, args); //将被代理对象传进去。args是参数
}
if(method.getName().equals("show")){
System.out.println("A类的show方法增强了");
return method.invoke(o, args);
}
return null;
}
}
//创建代理对象
class CreateJDKProxy{ //JDK的动态代理需要被代理对象有接口,之所以叫JDK动态代理是因为他依赖的是jdk,而cglib动态代理不要被代理对象有接口,他需要cglib的jar
public static void main(String[] args) {
final A a=new A();
JDKProxy j=new JDKProxy(a); //这个j对象其实是个拦截器,使用Proxy创建代理对象要传3个参数,一个是类加载器,一个是被代理对象的接口,一个是拦截器
//拦截器也可以采用内部类的方式,采用内部类的方式就不用写上面的哪个JDKProxy这个类了
//这个proxy对象就是A的代理对象,他能实现A类的所有功能,此外还能对A进行增强,这里采用了A类的接口B指向proxy代理对象
B proxy= (B) Proxy.newProxyInstance(CreateJDKProxy.class.getClassLoader(), a.getClass().getInterfaces(), j);
//采用匿名内部类的方式,个人感觉采用内部类的方式比较容易理解,而且代码也简单,new InvocationHandler()这是一个接口,上面写的拦截器就是实现了这个接口
B proxy2=(B) Proxy.newProxyInstance(CreateJDKProxy.class.getClassLoader(), a.getClass().getInterfaces(), new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("run")){
System.out.println("A类的run方法增强了");
return method.invoke(a, args); //将被代理对象传进去,args是参数,创建代理对象的时候不用传,使用代理对象的时候传,代理对象可以调用
} //被代理对象的所有方法,如A类中有一个run(int x),那么代理对象proxy2.run(1),在这个时候传参数1.
if(method.getName().equals("show")){
System.out.println("A类的show方法增强了");
return method.invoke(a, args); //不管方法有没有返回值都可以使用return
}
return null;
}
});
//用代理对象调用被代理对象的方法,从而增强被代理对象
proxy.run(1);
proxy.show();
}
}
//创建Wrap类包装A类,实现A的接口B
public class Wrap implements B{
private A a;
public Wrap(A a){
this.a=a;
}
public String run(int x) {
System.out.println("增强A的run方法");
return a.run(x); //用A类对象调用A类方法,然后在进行增强
}
public void show() {
System.out.println("增强A的show方法");
a.show();
}
}
//创建wrap对象
class CreateWrap{
public static void main(String[] args) {
//产生包装A类的Wrap对象
A a=new A();
B w=new Wrap(a);
w.show();
w.run(1);
}
}
---------------------- android培训、 java培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net/heima