代理模式分为静态代理和动态代理
静态代理
介绍
类似于生活中的中介代理房东租房、婚介代理要结婚的情侣布置婚礼现场等等。
实现
拿房东租房为例
Rent接口
package com.curtian.study.static_proxy.demo1;public interface Rent { void rent();}
Rent接口的第一个实现类,房东
package com.curtian.study.static_proxy.demo1;/** * 房东 */public class Host implements Rent{ @Override public void rent() { System.out.println("房东租房子"); }}
Rent接口的第二个实现类,中介
package com.curtian.study.static_proxy.demo1;public class Proxy implements Rent{ private Host host; @Override public void rent() { seeHouse(); host.rent(); hetong(); rate(); } public Proxy(Host host) { this.host = host; } private void seeHouse(){ System.out.println("中介带看房子"); } private void hetong(){ System.out.println("签署租赁合同"); } private void rate(){ System.out.println("收取中介费"); }}
从代码中我们也可以发现,中介只是在被代理的类的方法上加了一些额外的方法(seeHouse、hetong、rate)
静态代理总结
由接口(Rent租房接口)
、真实角色(Host房东)
、代理角色(Proxy房屋中介)
组成。
好处
是可以是使真实角色操作更加存粹(房东只管租房一件事情),很明显的体现了面向对象七大原则的单一职责原则。公共业务就交给代理角色。
缺点
一个真实角色就对应一个代理角色,比如房东对应房屋中介、要结婚的情侣对应婚介所
动态代理
介绍
拥有静态代理的所有优点以及可以动态生成代理类。
分类
动态代理分为三大类:
基于接口的:jdk动态代理基于类的:cglibjava字节码实现的:javasistJDK动态代理
(目前博主只了解了jdk动态代理)
JDK动态代理核心
Proxy类
和InvocationHandler接口
Proxy用于生成代理类,实现InvocationHandler接口可以通过反射获取被代理的类的方法, 然后在此基础上添加一些附属操作
举例
给所有类的方法加一些日志。
UserService接口
package com.curtian.study.static_proxy.demo2;public interface Userservice { void add(); void delete();}
UserServiceImpl类
package com.curtian.study.static_proxy.demo2;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl implements Userservice{ @Override public void add() { System.out.println("加法"); } @Override public void delete() { System.out.println("减法"); }}
ProxyInvocationHandler(核心)
package com.curtian.study.dynamic_proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyInvocationHandler implements InvocationHandler { //被代理的对象 private Object target; public void setTarget(Object target){ this.target = target; } /** * 生成代理类 * @return */ public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * 当代理类执行方法的时候,会回调到这个方法,附属操作也是在这里加的 * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(proxy.getClass().getName()); log("调用了" + method.getName() + "方法"); return method.invoke(target, args); } private void log(String msg){ System.out.println(msg); }}
Test(测试)
/** * 动态代理 * 介绍:动态代理和静态代理角色一样 * 动态代理的代理类是动态生成的,不是我们直接写好的! * 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。 * 1.基于接口--Jdk动态代理【本次示例】 * 2.基于类:cglib * 3.java字节码实现: javasist * 示例中的两个核心类/接口,Proxy类、invocationHandler接口 * * */public class Main { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(); proxyInvocationHandler.setTarget(userService); Userservice proxy = (Userservice) proxyInvocationHandler.getProxy(); proxy.add(); proxy.delete(); }}
运行情况: