代理模式
可以理解为一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
通过代码分析理解
//买房动作
public interface BuyHouse {
void buyHouse();
}
//客户直接买房
public class BuyHouseImpl implements BuyHouse {
@Override
public void buyHouse() {
System.out.println("我要买房子");
}
}
//通过代理(中介)买房
public class BuyHouseProxy implements BuyHouse {
BuyHouse buyHouse;
public BuyHouseProxy(BuyHouse buyHouse){
this.buyHouse=buyHouse;
}
@Override
public void buyHouse() {
System.out.println("买房前准备");
buyHouse.buyHouse();
System.out.println("买房后装修");
}
}
main测试
public class MianTest {
public static void main(String[] args){
BuyHouse buyHouse = new BuyHouseImpl();
BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
buyHouseProxy.buyHouse();
}
}
//执行结果
买房前准备
我要买房子
买房后装修
代理模式的应用场景:
1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。
2、虚拟代理,是根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真是对象。
3、安全代理,用来控制真实对象访问时的权限。
4、智能引用,是指当调用真实对象时,代理处理另外一些事。
2018/9/10修改
上述代理模式是基于静态代理的一种实现,那么下面来讲解基于jdk的动态代理
动态代理实现之jdk动态代理
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
实现原理:采用反射技术
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
代码实现(还是基于买房示例,现在我们只需创建一个动态代理类即可)
package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Author: chen
* @Description: jdk的动态代理
* @Date: created in 2018/9/10
* @Modified By:
*/
public class MyProxy implements InvocationHandler {
public Object target;
MyProxy(Object target){
this.target = target;
}
/**
* @param proxy 需要代理的真实类
* @param method 真实类的方法
* @param args 方法所需参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("++++++before " + method.getName() + "++++++");
Object result = method.invoke(target,args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
}
}
客户端
package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;
/**
* @Author: chenpengtao
* @Description:
* @Date: created in 2018/7/24
* @Modified By:
*/
public class MianTest {
public static void main(String[] args){
BuyHouse buyHouse2 = new BuyHouseImpl2();
MyProxy myProxy = new MyProxy(buyHouse2);
try {
BuyHouse subject = (BuyHouse) Proxy.newProxyInstance(myProxy.getClass().getClassLoader(),buyHouse2.getClass().getInterfaces(),myProxy);
subject.buyHouse();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
//执行结果
++++++before buyHouse++++++
我要买房子2
++++++after buyHouse++++++
动态代理实现之cglib代理
cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。不能对final修饰的类进行代理。
实现原理:采用字节码(asm)技术
还以买房为例,现在只需实现cglib代理类即可
package com.chenpt.designModel.proxyFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.annotation.Primary;
import java.lang.reflect.Method;
/**
* @Author: chen
* @Description: 基于cglib的动态代理
* @Date: created in 2018/9/10
* @Modified By:
*/
public class MyCglib implements MethodInterceptor{
private Object target;
//相当于JDK动态代理中的绑定
public Object getInstance(Object target) {
this.target = target; //给业务对象赋值
Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
enhancer.setCallback(this);
// 创建动态代理类对象并返回
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("预处理——————");
methodProxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
System.out.println("调用后操作——————");
return null;
}
}
客户端
package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;
/**
* @Author: chenpengtao
* @Description:
* @Date: created in 2018/7/24
* @Modified By:
*/
public class MianTest {
public static void main(String[] args){
BuyHouse buyHouse2 = new BuyHouseImpl2();
MyCglib myCglib = new MyCglib();
buyHouse2 = (BuyHouse) myCglib.getInstance(buyHouse2);
buyHouse2.buyHouse();
}
}
//执行结果
预处理——————
我要买房子2
调用后操作——————