1.代理模式readMe:
代理设计模式: 是java中常用的设计模式!
特点:
01.委托类和代理类有相同的接口或者共同的父类!
02.代理类为委托类负责处理消息,并将消息转发给委托类!
03.委托类和代理类对象通常存在关联关系!
一个代理类对象与一个委托类对象关联!
04.代理类本身并不是真正的实现者!而是通过调用委托类的方法,
来实现功能!
按照代理类创建的时机,代理类分为两种:
01.静态代理:由我们程序猿或者特定的工具自动生成了源代码,
在程序运行之前,.class文件已经存在了!
(serviceImpl 调用了 dao层的方法! 真正的实现是Dao)
02.动态代理:在程序运行期间,通过反射的方式动态的创建出来!
按照我们的使用方式: 是由共同的接口还是公共的父类?
01.jdk动态代理 (接口)
必须知道一个类和一个接口
001.InvocationHandler接口只有一个方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
proxy:代理类对象
method:被代理的方法
args:被代理的方法的参数列表
002.Proxy 类:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
loader:类加载器
interfaces:代理类实现的所有接口
h:InvocationHandler接口的一个实例 this当前对象
因为我们想使用jdk动态代理 必须是 代理类 实现 InvocationHandler!
它让我们传递父接口 我们传递 自身!
02.cglib动态代理(接口+父类)
必须知道一个类和一个接口
001.MethodInterceptor接口
public Object intercept(Object obj,
Method method,Object[] args,MethodProxy proxy) throws Throwable;
intercept是所有拦截器执行的方法,类似于jdk动态代理中的invoke
002. Enhancer类
设置委托类和代理类的公共接口或者公共的父类
public void setSuperclass(Class superclass) {
if (superclass != null && superclass.isInterface()) {
setInterfaces(new Class[]{ superclass });
} else if (superclass != null && superclass.equals(Object.class)) {
// affects choice of ClassLoader
this.superclass = null;
} else {
this.superclass = superclass;
}
}
代理类执行完毕 通知委托类
public void setCallback(final Callback callback) {
setCallbacks(new Callback[]{ callback });
}
在Enhancer类的父类AbstractClassGenerator中有一个方法
创建我们需要的代理类
protected Object create(Object key)
2.静态代理:
01.接口代码:
package cn.pb.dao;
/**
* 动物类 父接口
*/
public interface Animal {
//主业务
void eat();
void sleep();
}
02.实现类代码:
package cn.pb.dao.impl;
/**
* 狗狗类 实现了Animal接口
*/
import cn.pb.dao.Animal;
public class Dog implements Animal {
public void eat() {
System.out.println("狗狗在啃骨头!");
}
public void sleep() {
System.out.println("狗狗在午休!");
}
}
03.静态代理类:
package cn.pb.staticproxy;
import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;
/**
* 狗狗的静态代理类
*/
public class AnimalStaticProxy implements Animal {
private Dog dog;
public void sleep() {
System.out.println("主人在召唤"); //系统级业务
dog.sleep();
System.out.println("主人离开"); //系统级业务
}
public void eat() {
System.out.println("主人在召唤"); //系统级业务
dog.eat();
System.out.println("主人离开"); //系统级业务
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
/**
* 我们发现的问题
* 01:代码冗余
* 02:把冗余的代码提取成公共的方法
* 03:有可能小猫咪也有这些方法
* 04:提取成一个工具类中的方法
* 05:现在有一个小猫咪 也需要执行 sleep和eat 以及系统级业务方法
* 06:我们又得创建一个小猫咪对应的代理类
* 07:动物有很多 ,难道需要我们创建N个代理类吗??肯定!
*/
}
04.测试类代码:
/**
* 静态代理的测试方法
*/
@Test
public void testStaticProxy(){
AnimalStaticProxy proxy = new AnimalStaticProxy();
Dog dog=new Dog();
proxy.setDog(dog);
proxy.eat();
System.out.println("*************");
proxy.sleep();
}
3.JDK动态代理:
01.接口代码:
package cn.pb.dao;
/**
* 动物类 父接口
*/
public interface Animal {
//主业务
void eat();
void sleep();
}
02.实现类代码:
package cn.pb.dao.impl;
/**
* 狗狗类 实现了Animal接口
*/
import cn.pb.dao.Animal;
public class Dog implements Animal {
public void eat() {
System.out.println("狗狗在啃骨头!");
}
public void sleep() {
System.out.println("狗狗在午休!");
}
}
03.动态代理类代码:
package cn.pb.jdkdynamicproxy;
/**
* JDK的动态代理类
*/
import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class AnimalJdkDynamicProxy implements InvocationHandler {
/**
* 01.我们不确定委托类是谁?委托类的类型 是Object
* 和委托类建立关联关系
*/
private Object target;
/**
* 02.给我一个委托类,我返回一个代理类对象
*/
public Object createProxy(Object target){
//根据传递的参数 进行对象的关联
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
*
* @param proxy :代理对象
* @param method :方法名
* @param args : 参数列表
* @return
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("主人在召唤"); //系统级业务 开始事务
Object result= method.invoke(target,args); // 主业务
System.out.println("主人离开"); //系统级业务 日志处理 关闭事务
return result;
}
//创建测试方法
public static void main(String[] args) {
AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
Animal dog= (Animal) proxy.createProxy(new Dog());
dog.eat();
System.out.println("**************************");
dog.sleep();
}
}
04.测试代码:
@Test
public void testJdkDynamicProxy(){
AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
Animal dog= (Animal) proxy.createProxy(new Dog());
dog.eat();
System.out.println("**************************");
dog.sleep();
}
4.cglib动态代理:
01.接口代码:
package cn.pb.dao;
/**
* 动物类 父接口
*/
public interface Animal {
//主业务
void eat();
void sleep();
}
02.实现类代码:
package cn.pb.dao.impl;
/**
* 狗狗类 实现了Animal接口
*/
import cn.pb.dao.Animal;
public class Dog implements Animal {
public void eat() {
System.out.println("狗狗在啃骨头!");
}
public void sleep() {
System.out.println("狗狗在午休!");
}
}
03.动态代理类代码:
package cn.pb.cglibdynamicproxy;
/**
* Cglib动态代理
*/
import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;
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 AnimalCglibDynamicProxy implements MethodInterceptor {
/**
* 在enhancer中有一个setCallBack(this)
* 这样就实现了代理类和委托类的关联
*/
private Enhancer enhancer=new Enhancer();
/**
* 创建代理类对象
*/
public Object createProxy(Class clazz){
//设置公共的接口或者公共的类
enhancer.setSuperclass(clazz);
//建立关联关系
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 类似于我们jdk中的invoke
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("主人在召唤"); //系统级业务 开始事务
Object result= proxy.invokeSuper(obj,args); // 主业务
System.out.println("主人离开"); //系统级业务 日志处理 关闭事务
return result;
}
//创建测试方法
public static void main(String[] args) {
AnimalCglibDynamicProxy proxy=new AnimalCglibDynamicProxy();
//这里的参数可以传三种形式01:new Dog().getClass()
// 02:Class.forName("cn.pb.dao.impl.Dog") 03.Dog.class
Animal dog= (Animal) proxy.createProxy(new Dog().getClass());
dog.eat();
System.out.println("**************************");
dog.sleep();
}
}
04.测试代码:
@Test
public void testCglibDynamicProxy(){
AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
Animal dog= (Animal) proxy.createProxy(new Dog());
dog.eat();
System.out.println("**************************");
dog.sleep();
}