一、什么是代理模式
定义: 给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用。
目的:
①:功能增强:通过代理业务对原有业务进行增强
②:控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性
二、相关概念
目标类:原对象,我们需要代理对象控制他的访问,拓展其功能。
代理类:代理模式产生的对象,是原对象“替身”,已经在原有基础上修改逻辑
三、实现代理的三种方式
(1).静态代理
1.静态代理的特点
①:代理类是自己手动实现的,需要自己去创建一个类
②:代理类所代理的目标类是固定的
2.利用接口实现静态代理
静态代理逻辑图
关于接口的方式,我们在实现接口的时候,目标类和代理类都必须实现目标接口当中所实现的方法,从某种意义上代理类就可以帮我们实现目标类当中的方法,并且代理类还可以有自己的扩展方法。
3.代码实现
首先先定义接口
public interface ByClothes {
void clothes(String size);
}
定义目标对象
public class ClothesFactory implements ByClothes {
@Override
public void clothes(String size) {
System.out.println("已经为您制作好了一整套size为"+size+"的衣服。。。。。。。。");
}
}
制造代理对象
public class proxy implements ByClothes {
//被包含的真是对象
public ClothesFactory factory = new ClotheFactory;
// 对功能的增强
@Override
public void clothes(String size) {
FrontService();
factory.clothes(size);
endService();
}
//前置服务
public void FrontService() {
System.out.println("根据您的需求进行市场调研");
}
//前置服务
public void endService() {
System.out.println("为您提供一条龙的包办服务");
}
}
制造测试类------买衣服的人
public class Test {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.clothes("xxL");
}
}
4.静态代理存在的问题
①:当目标类曾多时,代理类也需要增多,导致代理类的关系不便。
②:当接口当中的功能增多或者修改,都会影响实体类,违反开闭原则(程序对访问开放,对修改关闭)
(2).JDK动态代理
1.静态代理和动态代理的区别
静态代理需要我们手动的去创建代理对象,动态代理则是采用jdk提供的方法创建代理对象
2.JDK动态代理的实现
使用java反射包当中的类和接口实现动态代理的功能
3.JDK动态代理逻辑图
4.jdk动态代理
新建接口
public interface ByShoot {
void byShoot(String size);
}
新建工厂
public class ShootFactory implements ByShoot{
@Override
public void byShoot(String size) {
System.out.println("已经为您生产出了尺码为"+size+"的鞋子");
}
}
代理类
public class LisiFactory implements InvocationHandler {
// 被代理的对象
private Object factory ;
public DyProxy(Object factory) {
this.factory = factory;
}
//三个参数的讲解
//1.Object:jdk创建的代理类,无需赋值
//2.Method:目标类当中的方法,jdk提供,无需赋值
//3.Object[]:目标类当中的方法的参数,jdk提供,无需赋值
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
FrontService();
method.invoke(factory, args); //这里的invoke(目标对象,方法参数)
endService();
return null;
}
// 前置服务
public void FrontService() {
System.out.println("根据您的需求进行市场调研");
}
// 后置服务
public void endService() {
System.out.println("为您提供一条龙的包办服务");
}
//该方法并不是固定的,但是内部的Proxy类的创建是核心
public Object getProxyInstance() {
// TODO Auto-generated method stub
return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
}
}
新建测试类
public class Test {
public static void main(String[] args) {
ClothesFactory clothesFactory = new ClothesFactory();
ByClothes clothes = (ByClothes) new 动态代理类(clothesFactory).hhh(); // 1.代理谁 //2.接口是什么
clothes.clothes("XXXL");
ShootFactory shootFactory = new ShootFactory();
ByShoot shoot = (ByShoot) new 动态代理类(shootFactory).hhh();
shoot.shoot("1000");
}
}
5.JDK代理类实现细节
①:InvocationHandler接口:里边只有一个invoke()方法
invoke()方法:表示我们要求代理对象要完成的功能
1).调用并执行目标的方法
2).功能增强,在目标对象调用时增强其功能
②:Proxy类:核心对象,其目的是创建道理对象
以前我们创建对象是new构造器,现在我们使用Proxy类的方法,代理new的使用
newProxyInstance()方法的作用是创建代理对象,其返回值就是代理对象
//ClassLoader loader:类的加载器,复杂向内存当中加载对象,使用反射的方式获取
// Class<?>[] interfaces:目标对象实现的接口,也是反射获取
//InvocationHandler h:代理类需要完成的功能
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
(3).cglib动态代理
1.jdk动态代理的问题
使用jdk动态代理存在一个问题,jdk提供的动态代理只能为拥有接口的类进行动态代理,但是对于没有实现接口的类,则没有办法进行动态代理。
2.什么是cglib动态代理
cglib是是第三方的工具库。其原理是继承,cglib通过继承目标类,创建他的子类,在子类当中重写父类的相关方法,实现功能的增强。
3.cglib基本结构
下图所示,代理类去继承目标类,每次调用代理类的方法都会被方法拦截器拦截,在拦截器中才是调用目标类的该方法的逻辑。
4.cglib实现动态代理的原理
1.生成一个空的字节码对象
2.通过字节码对象生成目标类对象的子类 进行增强
3.实现拦截器,通过连接器实现代理的类方法
4.创建代理对象
5.代码实现
CGLib动态代理中提供了一个类Enhance,需要用它生成一个空的字节码对象,所以我们需要导入外部的jar包依赖。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
目标类
/**
* 目标类
*/
public class ClothesFactory {
public void clothes(String size) {
System.out.println("已经为您制作好了一整套size为"+size+"的衣服。。。。。。。。");
}
}
拦截器
/**
* 实现拦截器,通过连接器实现代理的类方法
*/
public class MyMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 代理对象
* @param method 目标对象中的方法
* @param objects 目标对象中方法的参数
* @param methodProxy 代理对象中代理方法对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置增强");
methodProxy.invokeSuper(o,objects); // 动态的回调父类当中的方法
System.out.println("后置增强");
return o;
}
}
代理类
/**
* 代理类
*/
public class CglibProxy {
public static Object createProxy(String path) throws ClassNotFoundException {
Enhancer enhancer = new Enhancer(); //生成空的字节码对象
enhancer.setSuperclass(Class.forName(path)); //通过字节码对象生成目标类对象的子类 进行增强
enhancer.setCallback(new MyMethodInterceptor()); //实现拦截器,通过连接器实现代理的类方法
Object o = enhancer.create();//创建代理对象
return o;
}
}
测试
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//生成代理对象
ClothesFactory proxy = (ClothesFactory) CglibProxy.createProxy("com.qcby.ClothesFactory");
//方法调用
proxy.clothes("xxxL");
}
}