代理模式:
静态代理:类如结婚,我们需要找婚庆公司,而婚庆公司就是代理类,而我们需要结婚的人为被代理类,而结婚就是我们以及婚庆公司共同实现的一个目标。
用代码进行模拟。
首先要有一个接口,类如我们取一个Marry(结婚)作为该接口。
public interface Marry {
public void toMarry();
}
然后我们再去实现Marry接口的类,命名为You(你),这也是被代理的类
public class You implements Marry{
@Override
public void toMarry() {
// TODO Auto-generated method stub
System.out.println("你要结婚");
}
}
在定义一个代理类,命名Marrycompany(婚庆公司),这也是代理类
public class Marrycompany implements Marry{
private Marry marry;
public Marrycompany(Marry marry) {
super();
this.marry = marry;
}
@Override
public void toMarry() {
// TODO Auto-generated method stub
System.out.println("1111");
marry.toMarry();
System.out.println("222");
}
}
然后我们在定义一个类,命名start,用来运行代码,实现静态代理。
public class Start {
public static void main(String[] args) {
Marry youMarry=new You();
Marrycompany marryompany=new Marrycompany(youMarry);
marryompany.toMarry();
}
}
结果:
1111
你要结婚
222
静态代理是已知代理的类型,可以通过扩展代理类,进行功能的附加和增加,例如Marrycompany类中的toMarry方法写的。
动态代理:当我们不知道被代理的类型时,我们无法写相应的代理类,这时就可以使用动态代理,动态代理分为jdk动态代理及CGlib动态代理。
首先我们先来讲一下jdk动态代理:
直接看代码,讲解在代码下面:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy {
//目标对象
private Object target;
public JdkProxy(Object target) {
this.target=target;
}
//得到代理方法
public Object getProcy() {
//类加载器
ClassLoader loader=this.getClass().getClassLoader();
//得到代理对象接口
Class[] interfaces=target.getClass().getInterfaces();
InvocationHandler invocationHandler=new InvocationHandler() {
/**
* proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0
* method:我们所要调用某个对象真实的方法的Method对象
* args:指代代理对象方法传递的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("11111");
Object result=method.invoke(target, args);
//return 的是方法的返回值
return result;
}
};
Object object=Proxy.newProxyInstance(loader, interfaces, invocationHandler);
return object;
}
}
这次我们动态生成代理类,所以我们需要首先定义一个Object类,由于我们并不知道被代理的类,需要传入并被Object target对象获取(定义一个构造方法),在生成代理类的方法中,需要返回一个Object类型参数,这也是因为我们不知道传入的target是何类型。在方法中我们首先先得到类加载器,类加载器将会作为参数为我们生成代理类,然后我们需要得到代理对象接口,通过传入的target,然后我们还需要一个InvocationHandler的参数,InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法,在invoke方法中调用method.invoke便是调用代理对象中的方法,它需要一个Object返回值,return的是代理对象的返回值如果没有可以写null,在Object result=method.invoke(target, args);这代码上下可以实现代理对象功能的附加,我们再写一个start方法用来运行一下:
import java.lang.reflect.Proxy;
import com.lyt.statics.Marry;
import com.lyt.statics.You;
public class start {
public static void main(String[] args) {
//目标对象
Marry you=new You();
//得到代理对象
JdkProxy jdkProxy=new JdkProxy(you);
Marry object=(Marry) jdkProxy.getProcy();
//代理对象调用方法
object.toMarry();
}
}
运行结果:
11111
你要结婚
CGlib动态代理:我们直接看一下生成代理类的代码块:
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy{
private Object target;
public CglibProxy(Object target) {
super();
this.target = target;
}
public Object getProxy() {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
MethodInterceptor methodInterceptor=new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("cglib...");
return null;
}
};
enhancer.setCallback(methodInterceptor);
return enhancer.create();
}
}
测试代码:
import com.lyt.statics.Marry;
import com.lyt.statics.You;
public class CglibyTest {
public static void main(String[] args) {
Marry target=new You();
CglibProxy cglibProxy=new CglibProxy(target);
Marry proxy=(Marry) cglibProxy.getProxy();
proxy.toMarry();
}
}
cglib与jdk动态代理相似,但是cglib用在没有接口的代理对象,使用继承的方法来实现代理类的实现,而jdk是通过接口,这是两个的区别。
总结:
代理模式实现分类以及对应区别
静态代理:手动为目标对象制作代理对象,即在程序编译阶段完成代理对象的创建。
动态代理:在程序运行期动态创建目标对象对应代理对象。
jdk 动态代理:被代理目标对象 必须实现某一或某一组接口实现方式通过回调创建代理对象。
cglib 动态代理:被代理目标对象可以不必实现接口,继承的方式实现。
动态代理相比较静态代理,提高开发效率,可以批量化创建代理,提高代码复用率。