Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。
更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。
静态代理:
/**
* @Description : TODO
* @author : hmwh
* @Creation Date: 2020-06-06 13:44
*/
interface ClothFactor{
void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactor{
private ClothFactor factor; //使用被代理类对象进行实例化
public ProxyClothFactory(ClothFactor factor){
this.factor=factor;
}
@Override
public void produceCloth() {
System.out.println("开始");
factor.produceCloth();
System.out.println("停止");
}
}
//被代理类对象
class NikeClothFactory implements ClothFactor{
@Override
public void produceCloth() {
System.out.println("Nike");
}
}
public class StaticProxyTest {
public static void main(String[] args) {
//创建被代理类对象
NikeClothFactory nike = new NikeClothFactory();
//创建代理类对象
ProxyClothFactory factory = new ProxyClothFactory(nike);
factory.produceCloth();
}
}
输出结果
开始
Nike
停止
动态代理:
/**
* @Project Name : untitled
* @Package Name : aop
* @Description : TODO
* @author : hmwh
* @Creation Date: 2020-06-06 14:01
* @ModificationHistory Who When What
* -------- --------- --------------------------
*/
package aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Description : TODO
* @author : hmwh
* @Creation Date: 2020-06-06 14:01
*/
interface Human{
String getBelief();
void eat(String food);
}
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("I Like " + food);
}
}
/*
需要实现动态代理需要解决的问题
1、如何根据加载到内存中的被代理类,动态创建一个代理类及其对象
2、当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a
*/
class ProxyFactory{
//调用此方法,返回一个代理类对象
public static Object getProxyInstance(Object obj){ //obj:代理对象
MyInvocationHandler invocationHandler = new MyInvocationHandler();
invocationHandler.bind(obj);
//获取类的加载器,类的继承接口
Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),invocationHandler);
return instance;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public void bind(Object obj){
this.obj = obj;
}
//当通过代理类的对象,调用方法a时,就会自动调用如下方法:invoke()
//将被代理类需要执行的方法a的功能声明在invoke()中
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//method:即为代理类对象调用方法,此方法也作为被代理类对象要调用的方法
//obj:被代理类的对象
Object invoke = method.invoke(obj, objects);
//代理类对象调用的方法的返回值作为当前类中的invoke()的返回值
return invoke;
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动调用被代理类中同名方法
System.out.println(proxyInstance.getBelief());
proxyInstance.eat("汉堡");
System.out.println("------------------------");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactor proxyInstance1 = (ClothFactor) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyInstance1.produceCloth();
}
}
输出结果
I believe I can fly!
I Like 汉堡
------------------------
Nike
面向切面,将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码—解耦。
这里我们添加一个HumanUtil作为模拟这里我们添加一个HumanUtil作为模拟
/**
* @Project Name : untitled
* @Package Name : aop
* @Description : TODO
* @author : hmwh
* @Creation Date: 2020-06-06 14:01
* @ModificationHistory Who When What
* -------- --------- --------------------------
*/
package aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Description : TODO
* @author : hmwh
* @Creation Date: 2020-06-06 14:01
*/
interface Human{
String getBelief();
void eat(String food);
}
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("I Like " + food);
}
}
//----------
class HumanUtil{
public void method1(){
System.out.println("通用方法1---------------------");
}
public void method2(){
System.out.println("通用方法2---------------------");
}
}
//---------
/*
需要实现动态代理需要解决的问题
1、如何根据加载到内存中的被代理类,动态创建一个代理类及其对象
2、当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a
*/
class ProxyFactory{
//调用此方法,返回一个代理类对象
public static Object getProxyInstance(Object obj){ //obj:代理对象
MyInvocationHandler invocationHandler = new MyInvocationHandler();
invocationHandler.bind(obj);
//获取类的加载器,类的继承接口
Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),invocationHandler);
return instance;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public void bind(Object obj){
this.obj = obj;
}
//当通过代理类的对象,调用方法a时,就会自动调用如下方法:invoke()
//将被代理类需要执行的方法a的功能声明在invoke()中
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
HumanUtil util = new HumanUtil();
util.method1();
//method:即为代理类对象调用方法,此方法也作为被代理类对象要调用的方法
//obj:被代理类的对象
Object invoke = method.invoke(obj, objects);
util.method2();
//代理类对象调用的方法的返回值作为当前类中的invoke()的返回值
return invoke;
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动调用被代理类中同名方法
System.out.println(proxyInstance.getBelief());
proxyInstance.eat("汉堡");
System.out.println("------------------------");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactor proxyInstance1 = (ClothFactor) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyInstance1.produceCloth();
}
}
输出结果
通用方法1---------------------
通用方法2---------------------
I believe I can fly!
通用方法1---------------------
I Like 汉堡
通用方法2---------------------
------------------------
通用方法1---------------------
Nike
通用方法2---------------------