一、代理模式:
代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
(1).静态代理:
Singer singer=new WangBao();
ProxyWang proxyWang=new ProxyWang(singer);
proxyWang.singing();
总结:
ProxyWang 是静态代理类,WangBao是目标对象类,都实现了Singer 是接口,
1、静态代理模式并没有做到事务的重用
2、假设dao有100个类,100个proxy,接口中有多少方法,在proxy层就得实现多少方法,有多少方法就要开启和提交多少事务
3、如果一个proxy实现了多个接口,如果其中的一个接口发生变化(添加了一个方法),那么proxy也要做相应改变
(2)动态代理:
动态代理类:在程序运行时,运用反射机制动态创建而成。
JDK的动态代理必须具备四个条件:1、目标接口 2、目标类 3、拦截器 4、代理类
Singer singer=new XueZhiQian();
//jdk提供了一个类–第一个参数是类加载器,第二个参数是目标对象的class的实现接口,第三个参数是代理对象
Singer singer1 = (Singer) Proxy.newProxyInstance(singer.getClass().getClassLoader()
, singer.getClass().getInterfaces(), new ProxyAi(singer));
singer1.singing();
package com.offcn.text;
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/*
-
动态代理类jdk
-
*/
public class ProxyAi implements InvocationHandler{
private Object object;public ProxyAi(Object object) {
this.object = object;
}//只要你的调用目标对象的方法都会走这个方法
//第一个参数是你的代理对象,第二参数是你调用目标对象的方法(反射)
//第三个参数是你调用目标对象的方法里的参数
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
//第一个参数是调用目标对象的方法的类,第二参数是你要调用目标对象方法的参数
Object mm=null;
if (method.getName().equals(“singing”)){
System.out.println(“唱歌试唱成功”);
mm = method.invoke(object, args);
System.out.println(“唱歌wang”);}else if (method.getName().equals("dancing")){ System.out.println("dancing成功"); mm = method.invoke(object, args); System.out.println("dancingover"); } return mm;
}
}
优点:
1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。
2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体。
3、利用JDKProxy方式必须有接口的存在。
4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。
缺点:
1、在拦截器中除了能调用目标对象的目标方法以外,功能是比较单一的,在这个例子中只能处理事务
2、拦截器中的invoke方法的if判断语句在真实的开发环境下是不靠谱的,因为一旦方法很多if语句需要写很多。
(3).cglib代理:
前提先导入Cglib代理的jar包
package com.offcn.text;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
private Object object;
public Object getCglibProxy(Object object) {
this.object = object;
//创建或引入jar包中代理对象
Enhancer enhancer=new Enhancer();
//设置内加载器
enhancer.setClassLoader(this.object.getClass().getClassLoader());
//设置其父类
enhancer.setSuperclass(this.object.getClass());
//设置回调 只要走下面这个方法都会走回调
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}
/*
* MethodInterceptor--方法拦截器
* */
@Override
//这个方法就是你调用目标对象的方法都会执行这个方法
//第一个参数是你的目标对象的代理对象,第二个参数也是目标对象的方法,第三个参数是目标对象的方法参数
//第四个参数是你代理对象拦截方法的对象
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("sucesssful");
Object obj= method.invoke(object,args);
return null;
}
}
//实例化一个cglibProxy代理对象
CglibProxy cglibProxy=new CglibProxy();
Singer singer=new WangBao();
//参数代表目标对象singer
Singer singer1 =(Singer)cglibProxy.getCglibProxy(singer);
singer1.singing();
总结:
1、CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
2、用CGlib生成代理类是目标类的子类。
3、用CGlib生成 代理类不需要接口
4、用CGLib生成的代理类重写了父类的各个方法。
5、拦截器中的intercept方法内容正好就是代理类中的方法体 CGLIB和JDK动态代理区别:
JDK:
目标类和代理类实现了共同的接口
拦截器必须实现InvocationHandler接口,而这个接口中invoke方法体的内容就是代理对象方法体的内容
CGLIB:
目标类 是代理类的父类
拦截器必须实现MethodInterceptor接口,而接口中的intercept方法就是代理类的方法体,使用字节码增强机制创建代理对象的.