设计模式(Design Pattern),其实就是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。分为三大类型,分别是:创建型模式、结构性模式、行为型模式。7大设计原则:开闭原则、接口隔离原则、合成复用原则、里氏替换原则、最少原则(迪米特法则)、单一职责原则、依赖倒置原则。具体的详细介绍大家自行百度,搜索。
代理模式的主要角色有三个:
抽象主题(Subject):定义了真实主题和代理主题的公共接口,使得在任何使用真实主题的地方都可以使用代理主题。
真实主题(RealSubject):实现了抽象主题的接口,定义了真实的业务逻辑,是代理主题所代表的真实对象。
代理主题(Proxy):也实现了抽象主题的接口,但是在调用真实主题的方法之前或之后,可以执行一些额外的操作,从而对真实主题进行控制或增强。
静态代理
抽象主题接口
/**
* @version 1.0.0
* @className: Subject
* @description: 抽象主题接口
* @author: zhangjunfa
* @date: 2023/8/29 9:13
*/
public interface Subject {
/**
* 程序猿工作类
*/
public void work();
}
真实的主题对象类
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* @version 1.0.0
* @className: UserWork
* @description: 程序猿工作类,也是真实的主题类。实现了 抽象主题接口
* @author: zhangjunfa
* @date: 2023/8/29 9:21
*/
@Slf4j
public class UserWork implements Subject {
/**
* 程序猿工作类,这是真实的业务逻辑
*/
public void work() {
log.info("我是一只《只会写Bug的程序猿》,我今天需要码字10W,date:{}", new Date());
}
}
代理主题类
import lombok.extern.slf4j.Slf4j;
/**
* @version 1.0.0
* @className: Proxy
* @description: 代理主题类,实现了抽象主题接口
* @author: zhangjunfa
* @date: 2023/8/29 9:24
*/
@Slf4j
public class Proxy implements Subject {
/**
* 真实的主题对象类,程序猿工作
*/
private UserWork userWork;
/**
* 构造器
*
* @param userWork
*/
public Proxy(UserWork userWork) {
this.userWork = userWork;
}
/**
* 程序猿工作类
*/
public void work() {
log.info("在调用真实的主题类之前,把5W的码字工作分给 张三。。。。{}", new User(1L, "张三", "疯狂码字"));
// <只会写Bug的程序猿> 在努力的工作。。。。。。。。。
// 这个地方就是 真实的主题类,就是我这只程序猿。我要做的就是真实的业务逻辑。(就是码字10W)
userWork.work();
log.info("在调用真实的主题类之后,又把5W的码字工作分给 李四。。。。{}",new User(4L,"李四","疯狂码字"));
}
}
测试
public class ApiTest {
// ApiTest.
@Test
public void test() {
// 真实的主题对象
UserWork userWork = new UserWork();
// 代理对象,并传入真实主题对象
Proxy proxy = new Proxy(userWork);
// 使用代理对象来调用抽象方法
proxy.work();
}
/*
代理对象在调用真实对象的方法之前和之后,都执行了一些额外的操作,
从而对真实对象进行了增强或控制。
本例中。我需要码字10W,在调用真实对象前。我把5W的码字工作交给
了张三。调用之后又把5W的码字工作交给了李四。
/手动滑稽的笑,我在偷懒。
*/
}
结果:
Jdk动态代理
代理类
/**
* @version 1.0.0
* @className: JdkProxy
* @description: 代理类
* @author: zhangjunfa
* @date: 2023/3/31 9:58
*/
@Slf4j
public class ProxyHandler<T> implements InvocationHandler {
private final T target;
public ProxyHandler(T target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("代理前-----");
Object result = method.invoke(target, args);
log.info("代理后-----代理方法:{},参数:{}", method.getName(), args);
return result;
}
}
代理类工厂类
/**
* @version 1.0.0
* @className: JdkProxy
* @description: 代理类工厂类
* @author: zhangjunfa
* @date: 2023/3/31 10:06
*/
public class ProxyFactory<T> {
private T target;
public ProxyFactory(T target) {
this.target = target;
}
public T newInstance() {
ProxyHandler<T> jdkProxyHandler = new ProxyHandler<T>(target);
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), jdkProxyHandler);
}
}
用户Service
/**
* @version 1.0.0
* @className: UserService
* @description:
* @author: zhangjunfa
* @date: 2023/3/31 9:55
*/
public interface UserService {
void addUser(String id,String name);
Object getUserById(String id);
}
测试
@Test
public void test_Proxy() {
ProxyFactory<UserService> factory = new ProxyFactory<UserService>(new UserServiceImpl());
UserService userService = factory.newInstance();
userService.addUser("1","Rosszhang");
Object username = userService.getUserById("1");
log.info("测试结果:{}", username);
}
Cglib动态代理
引入Cglib类库
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
用户接口和实现类
import com.ross.mode.User;
/**
* @version 1.0.0
* @className: UserService
* @description: 用户操作接口
* @author: zhangjunfa
* @date: 2023/8/29 13:20
*/
public interface UserService {
/**
* 新增用户
* @param user
*/
void addUser(User user);
}
/*********优美且自带华丽的分割线*******************/
import com.ross.mode.User;
import lombok.extern.slf4j.Slf4j;
/**
* @version 1.0.0
* @className: UserServiceImpl
* @description: 用户操作接口实现类
* @author: zhangjunfa
* @date: 2023/8/29 13:28
*/
@Slf4j
public class UserServiceImpl implements UserService {
/**
* 新增用户
*
* @param user
*/
@Override
public void addUser(User user) {
log.info("新增了一条用户数据:{}", user);
}
}
开启事务控制
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @version 1.0.0
* @className: Mapper
* @description: 开启事务控制,个人理解:相当于需要代理的操作。。
* @author: zhangjunfa
* @date: 2023/8/29 13:36
*/
@Slf4j
public class MapperTransactional {
public void before(Object o, Method method, Object[] args, MethodProxy methodProxy) {
// 如果输出 o ,会卡
log.info("开启事务操作。。。。。。方法:{},参数:{}", method.getName(), args);
}
public void after(Object o, Method method, Object[] args, MethodProxy methodProxy) {
// 如果输出 o ,会卡
log.info("关闭事务操作.......方法:{},参数:{}", method.getName(), args);
}
}
代理类
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @version 1.0.0
* @className: Proxy
* @description: 代理类
* @author: zhangjunfa
* @date: 2023/8/29 13:22
*/
@Slf4j
public class ProxyInterceptor implements MethodInterceptor {
/**
* 目标对象
*/
private UserService target;
/**
* 事务控制
*/
private MapperTransactional transactional;
/**
* 构造器
*
* @param target
*/
public ProxyInterceptor(UserService target, MapperTransactional transactional) {
this.target = target;
this.transactional = transactional;
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
transactional.before(o, method, args, methodProxy);
Object result = method.invoke(target, args);
transactional.after(o, method, args, methodProxy);
return result;
}
//返回一个代理对象: 是 target 对象的代理对象
public Object getProxyInstance() {
//1. 创建一个工具类
Enhancer enhancer = new Enhancer();
//2. 设置父类
enhancer.setSuperclass(target.getClass());
//3. 设置回调函数
enhancer.setCallback(this);
//4. 创建子类对象,即代理对象
return enhancer.create();
}
}
测试
// ApiTest.
@Test
public void test_CGLIB() {
//创建目标对象
MapperTransactional trascation = new MapperTransactional();
UserService target = new UserServiceImpl();
//获取到代理对象,并且将目标对象传递给代理对象
UserService userService = (UserService) new ProxyInterceptor(target, trascation).getProxyInstance();
//执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用
userService.addUser(new User(4L,"张三","疯狂的写BUG"));
}
测试结果
以上测试案例的代码集合:源码地址:项目名称:ross-proxy-03
测试案例源码地址
注意:以上代码都是个人的理解,如有不当之处,还望指正,共同进步。同时也希望大家能给我更通俗易懂的案例。来加深理解。/360度鞠躬致谢。
下面这个是我的个人公共号 只会写Bug的程序猿,大家可以关注一下。相互交流学习。
Ross zhang的博客
RossZhang的CSDN地址