最近学习了代理模式,在此做一个记录
一、概念
1、代理模式解决的问题:将主要业务、次要业务解耦
2、代理模式的本质:监听某一种行为,当改行为发生的时候对行为进行修饰,此处行为可以看做主要业务,修饰可以看成次要业务
3、代理模式的组成:
a、业务接口:申明需要被监听的行为
b、代理实现类(InvocationHandler):次要业务,次要业务和主要业务绑定执行
c、代理对象(监听对象)
二、静态代理和动态代理
1、静态代理
a、接口
/** * @program: demo * @description: 接口 * @author: bang.chen * @create: 2018-06-25 22:21 **/ public interface IUserDao { void save(); }
b、接口实现类、目标对象
/** * @program: demo * @description: 接口实现、目标对象 * @author: bang.chen * @create: 2018-06-25 22:22 **/ public class UserDao implements IUserDao{ @Override public void save() { System.out.println("数据已经保存"); } }
c、代理类
/** * @program: demo * @description:代理类 * @author: bang.chen * @create: 2018-06-25 22:24 **/ public class UserProxy implements IUserDao{ private IUserDao target; public UserProxy(IUserDao target){ this.target = target; } @Override public void save() { System.out.println("before do something....."); target.save(); System.out.println("after do something......"); } }
d、客户端测试
/** * @program: demo * @description: 客户端 * @author: bang.chen * @create: 2018-06-25 22:27 **/ public class App { public static void main(String[] args) { UserDao userDao = new UserDao(); UserProxy userProxy = new UserProxy(userDao); userProxy.save(); } }
输出结果
before do something..... 数据已经保存 after do something......
通过静态代理,已经对目标对象的行为进行了修饰
在实际开发中,一般不涉及静态代理,一般用到的都是动态代理,下面对动态代理进行介绍
2、动态代理
业务场景如下:
主要业务:吃法,便便;次要业务:洗手
a、业务接口
/** * Created by chenbang on 2019/12/9. * 业务接口 */ public interface BaseService { void eatFood(String food); void wcing(String str); }
b、代理对象实现类
/** * Created by chenbang on 2019/12/9. * 代理对象 */ public class Agent implements InvocationHandler { private BaseService baseService; public Agent(BaseService baseService) { this.baseService = baseService; } /** * * @param proxy 监听对象 * @param method 监听方法 * @param args 监听方法的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.equals("eatFood")){ wash(); method.invoke(baseService, args); }else if(methodName.equals("wcing")){ method.invoke(baseService, args); wash(); } return null; } private void wash(){ System.out.println("洗手"); } }
c、代理工厂(用于创建代理类、监听对象)
/** * Created by chenbang on 2019/12/9. * 代理工厂 */ public class ProxyFactory { public static BaseService newInstance(Class classFile) throws IllegalAccessException, InstantiationException { BaseService baseService = (BaseService) classFile.newInstance(); //获取一个代理对象 InvocationHandler agent = new Agent(baseService); //注册一个对特定行为监控的对象 Class classArray[] = {BaseService.class}; /** * classLoader:指向别监控的类文件在内存中的地址 * classArray:被监听的类中接口 */ return (BaseService) Proxy.newProxyInstance(BaseService.class.getClassLoader(), classArray, agent); } }
d、业务实现类
/** * Created by chenbang on 2019/12/9. */ public class Person implements BaseService{ @Override public void eatFood(String food) { System.out.println("狼吞虎咽吃"+food); } @Override public void wcing(String str) { System.out.println("舒爽的"+str); } } /** * Created by chenbang on 2019/12/9. */ public class Dog implements BaseService{ @Override public void eatFood(String food) { System.out.println("吭"+food); } @Override public void wcing(String str) { System.out.println("三腿立"+str); } }
e、测试类
/** * Created by chenbang on 2019/12/9. */ public class TestMain { public static void main(String[] args) throws InstantiationException, IllegalAccessException { // BaseService service = ProxyFactory.newInstance(); // service.eatFood(""); BaseService xiaoming = ProxyFactory.newInstance(Person.class); xiaoming.eatFood("鸡"); BaseService dog = ProxyFactory.newInstance(Dog.class); dog.eatFood("骨头"); } }
输出结果
洗手 狼吞虎咽吃鸡 Disconnected from the target VM, address: '127.0.0.1:52347', transport: 'socket' 洗手 吭骨头
总结
代理模式在开发中的使用简化了开发内容的复杂对,开发人员只需要关注主要业务,次要业务可以通过代理模式解决;实际使用的案例有,mybatis的面向接口编程,springAop......