代理模式(静态代理和动态代理)
文章目录
前言
应用场景:
1,因为某些原因无法直接操作目标类对象
eg. 比如登录某个网站时,有时候是被授权的管理员才能登录,一般用户是无法登录的,这个时候如果一般用户想要进行操作,就需要用到代理模式,将自己要进行的操作交给管理员来代理
2,对较多方法执行相同的操作
eg.比如在执行一些列方法之前添加开始日志,方法结束之后添加结束日志等功能。使用代理模式,降低了业务代码和目标方法的耦合度。提高了代码的性能,而且还解决了代码的大量冗余
一、静态代理是什么?
静态代理常常有一个接口,一个目标类,一个代理类,目标类和代理类需要实现同一个接口
静态代理也就是在程序运行前就已经存在代理类的字节码文件,代理类和目标类类的关系在运行前就确定了
1.定义接口
package com.wt.service;
import com.wt.pojo.User;
public interface UserService {
int addUser(User user);
int deleteUser(int id);
}
2.定义目标类(功能是模拟的)
package com.wt.service.impl;
import com.wt.pojo.User;
import com.wt.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public int addUser(User user) {
System.out.println("新增到数据库一个新用户");
return 1;
}
@Override
public int deleteUser(int id) {
System.out.println("删除一个用户");
return 1;
}
}
3.定义代理类
package com.wt.proxy;
import com.wt.pojo.User;
import com.wt.service.UserService;
import com.wt.service.impl.UserServiceImpl;
import com.wt.tx.Transacation;
public class UserServiceProxy implements UserService {
Transacation tx=new Transacation();
UserService userService=new UserServiceImpl();
@Override
public int addUser(User user) {
tx.TXopen();
userService.addUser(user);
tx.TXclose();
return 1;
}
@Override
public int deleteUser(int id) {
tx.TXopen();
userService.deleteUser(id);
tx.TXclose();
return 1;
}
}
4.定义事务类
package com.wt.tx;
public class Transacation {
public void TXopen(){
System.out.println("今天开始工作");
}
public void TXclose(){
System.out.println("今天下班了");
}
}
5.测试代码
import com.wt.pojo.User;
import com.wt.proxy.UserServiceProxy;
import com.wt.service.UserService;
import com.wt.service.impl.UserServiceImpl;
import org.junit.jupiter.api.Test;
public class TestUser {
@Test
public void Test1(){
UserService userService= new UserServiceProxy();
User user= new User();
userService.addUser(user);
System.out.println("=================");
userService.deleteUser(1);
}
}
6.测试结果
二、动态代理
动态代理:对于一个实现了一个接口的类(目标类,委托类i)增加一些其他的方法比如日志,事务等。可以给这个类创建一个代理类来完成这个操作,代理类需要实现相同的接口,这种方法降低了代码的耦合度。它与静态代理的区别是:动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
1.相关方法
1.1Proxy类
它是JDK封装的类,对于动态代理,调用Proxy.newProxyInstance()方法创建代理对象
它包含3个参数
第一个参数:目标类的Class获取
第二个参数:目标类的接口获取
第三个参数:拦截器(实现Invocationhandle接口的类实例)
1.2new InvocationHandler()匿名类
是实现lInvocationhandle接口的实例,该实例会调用接口中的方法invoke()
1.3invoke()
invoke()是Invocationhandle接口中定义的方法,实现了该接口的实现类需要重写这个方法,该方法有三个参数,第一个Proxy可以通过它反射获取代理对象信息,第二个method通过该方法可以执行目标类对象中的方法,第三个参数args是一个数组参数,表示目标对象方法中的参数
2.实现步骤
2.1创建接口
package com.wt.pojo;
public interface Person {
void giveMoney();
}
2.2创建目标对象类
package com.wt.pojo;
//被代理类
public class Student implements Person{
@Override
public void giveMoney() {
System.out.println("学生王宝强,上交班费");
}
}
2.3测试类中创建生成代理对象
package com.wt.test;
import com.wt.pojo.Person;
import com.wt.pojo.Student;
import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TestPerson {
@Test
public void test1(){
//创建目标类对象
final Person s1=new Student();
//获取一个代理对象
Person p1=(Person) Proxy.newProxyInstance(s1.getClass().getClassLoader(), s1.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("这位同学最近表现不错!");
Object result= method.invoke(s1,args);
System.out.println("老师他交了班费,学习也比较好,您应该表扬他");
return result;
}
});
p1.giveMoney();
}
}
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context