代理模式:java中23种设计模式之一
一个类不能或不方便访问另一个类时,通过代理来间接进行访问,代理起到桥梁的作用
java开发原则:
开闭原则 (每一个模块只做一件事情,解耦)
单一职责原则 (一个类不能或不方便访问另一个类时,通过代理来间接进行访问,代理起到桥梁的作用)
静态代理
实现步骤:
1. 分为代理者和被代理者(代理者与被代理者有相同的功能,也就是实现相同的接口)
2. 代理者包含一个被代理者的对象(代理者对象传入被代理者对象中)
3. 代理者调用方法时,要调用被代理者的方法,同时再加入新功能
共同接口
package com.cdz.static_agent_computer;
public interface IComputerSell {
/**
* 卖电脑
*/
void sellComputer();
}
电脑生产商
package com.cdz.static_agent_computer;
/**
* 电脑生产商(被代理者)
*/
public class MiComputerFactory implements IComputerSell{
/**
* 相同方法:销售电脑
*/
@Override
public void sellComputer() {
System.out.println("卖小米电脑");
}
}
电脑销售商
package com.cdz.static_agent_computer;
/**
*电脑代理商(代理者)
*/
public class MiComputerShop implements IComputerSell {
private IComputerSell miComputerFactory;
//代理者包含被代理者的对象,将被代理者对象传入到代理者对象中
public MiComputerShop(IComputerSell miFactory){
this.miComputerFactory=miFactory;
}
/**
* 都有的方法:销售电脑
* 并加入新功能
*/
@Override
public void sellComputer() {
//扩展功能
System.out.println("给电脑公司打广告");
//调用被代理者方法
miComputerFactory.sellComputer();
System.out.println("给电脑做销售");
}
}
测试:
package com.cdz.test;
import com.cdz.static_agent_computer.HuaWeiFactory;
import com.cdz.static_agent_computer.IComputerSell;
import com.cdz.static_agent_computer.MiComputerShop;
public class AgentTest {
public static void main(String[] args) {
//创建被代理者对象
IComputerSell miFactory = new HuaWeiFactory();
//创建代理者对象
IComputerSell miShop =new MiComputerShop(miFactory);
//调用代理方法
miShop.sellComputer();
}
}
注:静态代理的代理者只能代理一种业务,如果有多个业务就需要多个代理者
动态代理
原理:通过动态代理创建类,传入实现不同接口的被代理对象,会通过反射读取被代理对象的属性和方法,创建新代理类
(生成字节码),再创建代理类的对象。
动态代理实现方法:
一、. JDK动态代理
实现步骤:
1. 实现InvocationHandler接口
2. 代理者包含一个被代理者的对象(代理者对象传入被代理者对象中)
3. 实现接口方法invoke方法,在方法中调用被代理者方法,并扩展功能
4. 使得Proxy. newProxyInstance创建代理对象
第二步同上不需要实现方法即可
第一步,第三、四步:
package com.cdz.jdkagent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//应用技术反射
public class MyJDKAgentShop implements InvocationHandler {
//定义一个被代理者的对象
private Object factory;
//实现接口方法invoke
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//功能扩展
System.out.println("给产品打广告");
//调用被代理者的方法(实现原理:反射)
method.invoke(factory,objects);
System.out.println("给产品做销售");
return null;
}
//设置被代理者对象,使用Proxy.newProxyInstance并创建代理者对象
public Object setFactory(Object factory) {
this.factory = factory;
//创建代理对象
Object p = Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
this);
return p;
}
}
测试:
package com.cdz.test;
import com.cdz.static_agent_computer.IComputerSell;
import com.cdz.static_agent_computer.MiComputerFactory;
import com.cdz.jdkagent.MyJDKAgentShop;
import com.cdz.static_agent_tel.ITelSell;
import com.cdz.static_agent_tel.MiTelFactory;
public class JDKAgentTest {
public static void main(String[] args) {
//创建电脑的被代理对象
IComputerSell sell1=new MiComputerFactory();
//创建手机的被代理对象
ITelSell sell2= new MiTelFactory();
//创建动态代理对象
MyJDKAgentShop shop=new MyJDKAgentShop();
//创建电脑的动态代理对象
IComputerSell proxy1 = (IComputerSell)shop.setFactory(sell1);
//调用代理对象
proxy1.sellComputer();
//创建卖手机的动态代理对象
ITelSell proxy2 = (ITelSell) shop.setFactory(sell2);
//调用代理对象
proxy2.sellTel();
}
}
invoke方法参数:
Object invoke(Object proxy, Method method, Object[] args)方法
proxy 代理者对象
method 需要调用方法
args 参数的数组
返回值是method调用后的结果
Proxy.newProxyInstance对象的参数:
Object p = Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);
ClassLoader classLoader, 类的加载器,被代理对象.getClass().getClassLoader()
Class[] interfaces, 被代理对象实现接口的数组,被代理对象.getClass().getInterfaces()
InvocationHandler h 代理对象,this
二、 CGLIB动态代理
被代理的类不需要实现接口,CGLib是通过继承机制实现的,CGLib是动态生成了被代理类的子类,被代理的类必须能被继承。
实现步骤:
1. 引入依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2. 实现MethodInterceptor接口
3. 使用Enhancer创建代理对象
//2. 实现接口
public class MyCGLibShop implements MethodInterceptor {
//被代理对象
private Object factory = null;
public Object createProxy(Object factory){
this.factory = factory;
//3. 帮助创建代理类的工具
Enhancer enhancer = new Enhancer();
//给代理类设置父类
enhancer.setSuperclass(this.factory.getClass());
//设置方法的回调(调用代理对象的方法时执行的代码)
enhancer.setCallback(this);
//创建并返回代理类的对象
return enhancer.create();
}
4. 创建代理者调用方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLib给产品打广告");
//调用父类(被代理者)的方法
methodProxy.invokeSuper(o,objects);
System.out.println("CGLib给产品做售后");
return null;
}
}