代理模式:proxy,surrogate,在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
Spring aop的面向切面进行开发,实现的原理就是使用动态代理设置模式。
一,代理设置模式
jdk:静态代理,动态代理(非常常用)。
cglib生成的动态代理。
二,jdk静态代理
例,首先创建singer 歌手接口
public interface Singer {
//唱歌接口,跳舞接口
public void singing();
public void danceing();
}
创建一个王宝强,为歌手实现类:
public class wangBaoQiang implements Singer{
@Override
public void singing() {
System.out.println("正在唱歌");
}
@Override
public void danceing() {
System.out.println("正在跳舞");
}
}
再创建一个代理对象(经纪人):
//代理对象
//首先代理对象也要实现接口
//也要调用王宝强(目标对象的方法)
public class ProxyWang implements Singer{
private Singer singer;
public ProxyWang(Singer singer) {
this.singer = singer;
}
@Override
public void singing() {
System.out.println("舞台搭建成功");
singer.singing();
}
@Override
public void danceing() {
System.out.println("请开始跳舞");
singer.danceing();
}
}
创建test类
首先实例化对象是王宝强(目标对象)
Singer singer=new wangBaoQiang();
//实例化代理对象来调用其方法,在目标对象前后做一些相关操作
ProxyWang proxyWang=new ProxyWang(singer);
proxyWang.singing();
其结果为
舞台搭建成功
正在唱歌
静态代理:优点 好理解,
缺点:扩展性差,每次生成的只要有不同类,即使操作一样,也要重新生成一个代理对象。
三,jdk动态代理。
首先新增一个明星 孙笑川;
public class SunXiaoChuan implements Singer{
@Override
public void singing() {
System.out.println("孙哥正在唱歌");
}
@Override
public void danceing() {
System.out.println(
"孙哥正在跳舞"
);
}
}
设置代理:
//实现动态代理
public class ProxyAi implements InvocationHandler {
private Object object;
//构造函数 用到的object
public ProxyAi( Object object){
this.object=object;
}
//重写的方通过只要你调用目标对象方法,都会走
//第一个参数是你的代理对象,第二个参数是你调用目标对象的方法(通过反射来实现)
//第三个参数是你调用对象的方法用的参数,
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这个参数 invoke就是通过反射来调用目标对象的方法,第一个参数是你要调用目标对象方法的类
//第二个参数是你要调用目标对象方法的参数
Object O=null;
if(method.getName().equals("singing")){
System.out.println("搭建舞台,市场成功");
O= method.invoke(object,args);
System.out.println("唱歌结束");
}else if(method.getName().equals("danceing")){
System.out.println("可以跳舞");
O= method.invoke(object,args);
System.out.println("演出结束");
}
return null;
}
}
在text中使用动态代理
jdk提供了这样一个类,代理的意思
第一个参数叫类加载器,
第二个参数是目标对象的class,注意是类的.class
第三个参数是代理对象
Singer singer=new SunXiaoChuan();
//jdk提供了这样一个类,代理的意思
//第一个参数叫类加载器,
// 第二个参数是目标对象的class,注意是类的.class
//第三个参数是代理对象
//返回值为object,这里强转为了singer类
Singer singer1= (Singer) Proxy.newProxyInstance(
singer.getClass().getClassLoader(),
new Class[]{Singer.class},
new ProxyAi(singer));
singer1.singing();
singer1.danceing();
结果为
搭建舞台,市场成功
孙哥正在唱歌
唱歌结束
可以跳舞
孙哥正在跳舞
演出结束
四,cglib生成的动态代理。
首先导包,并buiding path,
创建cgLibProxy,实现MethodInterceptor
public class CgLibProxy implements MethodInterceptor {
//MethodInterceptor 方法拦截器
//第一个参数是你的代理对象,
//第二个参数是你的目标对象的方法
//第三个参数是你的目标对象的方法参数
//第四个是你代理对象拦截方法的对象
//先实例化对象
private Object object;
//创建代理对象,也可以用set方法
public Object getCgLibProxy(Object object){
this.object=object;
//得到创建代理对象的对象,enhancer都是jar内封装好的
Enhancer enhancer =new Enhancer();
//设置类加载器
enhancer.setClassLoader(this.object.getClass().getClassLoader());
//设置其父类
enhancer.setSuperclass(this.object.getClass());
//设置回调,只要走下面这个方法都会走回调
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
//这个方法就是在调用目标对象的方法都会执行这个方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("先彩排唱歌");
Object ob= method.invoke(object, objects);
return ob;
}
}
text中:
//实例化一个cglibproxy 代理对象这个类
//这个参数代表我们的目标对象
CgLibProxy cgLibProxy=new CgLibProxy();
Singer singer= new wangBaoQiang();
Singer singer2= (Singer) cgLibProxy.getCgLibProxy(singer);
singer2.singing();
}
结果为:
先彩排唱歌
正在唱歌
五,小结
动态代理:利用java的反射来实现。非常常用