目录
1、什么是代理模式
代理模式为某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。这样做的好处:扩展目标对象的功能,核心功能是方法增强。代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
代理有不同的形式:静态代理和动态代理。其中动态代理包括 JDK代理和cglib代理。
2、静态代理
实现静态代理的步骤:
-
代理类跟目标类需要实现同一个接口的方法,
-
在代理类中定义目标的对象,编写代理方法,在代理方法中使用目标对象的方法及一些扩展操作。
-
创建代理类对象和目标对象,将目标对象传给代理类对象,代理类对象使用代理方法。
代码实现:
1、首先,我们创建一个Siner接口。这个接口就是歌星(被代理类),和经纪人(代理类)的公共接口,他们都有上唱歌的行为。这样,歌星唱歌就可以让经纪人来代理执行,经纪人可以在歌星唱歌前、后进行增强。
public interface Singer {
/**
* 歌星都能唱歌
*/
void sing();
}
2、创建被代理对象实现接口,完成具体的业务逻辑
MaleSinger 类实现Singer接口。MaleSinger 可以具体实唱歌的动作:
/**
* 男歌星
*/
public class MaleSinger implements Singer{
private String name;
public MaleSinger(String name) {
this.name = name;
}
/**
* 歌星都能唱歌
*/
public void sing() {
System.out.println(name+"开始唱歌了……");
}
}
3、 创建代理类实现接口,完成委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
/**
* 经纪人
*/
public class Agent implements Singer{
private Singer singer;
public Agent(Singer singer) {
this.singer = singer;
}
/**
* 歌星都能唱歌
*/
public void sing() {
System.out.println("节目组找过来!需要演出,谈好演出费用。。。。。");
singer.sing();
System.out.println("结算费用,下一次合作预约。。。。。。");
}
}
4、客户端使用操作与分析
public class StaticProxyTest {
public static void main(String[] args) {
//被代理的歌星周杰伦,他的唱歌由代理对象agent(经纪人)完成
Singer singer=new MaleSinger("周杰伦");
//生成代理对象,并将周杰伦传给代理对象
Agent agent=new Agent(singer);
//由代理对象经纪人代理唱歌
agent.sing();
}
}
缺点:代理对象需要和目标对象实现一样的接口,所以会产生很多的代理类。一旦增加方法,目标类和代理类都要进行维护。
3、动态代理
1、JDK代理
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。JDK动态代理的前提是必须有接口,JDK 动态代理会为每个业务接口动态生成相应的代理类实现,并加载到 JVM 中,然后创建对应的代理实例对象。
JDK 动态代理的实现原理:动态创建代理类,然后通过指定类加载器进行加载。
代码实现:
接口:
UserService
/**
* @author :Rk.
* @date : 2022/9/10
*/
public interface UserService {
String findAllUsers();
}
接口实现类:
/**
* @author :Rk.
* @date : 2022/9/10
*/
public class UserServiceImpl implements UserService {
@Override
public String findAllUsers() {
System.out.println("查询所有用户");
return "查询到用户:12345";
}
}
使用jdk动态代理实现代理类:
/**
* @author :Rk.
* @date : 2022/9/10
*/
public class UserTest {
public static void main(String[] args) {
UserServiceImpl userServiceimpl=new UserServiceImpl();
UserService userService = (UserService)Proxy.newProxyInstance(UserTest.class.getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强
System.out.println("在查询前进行增强!");
//调用userservice中的findall方法
Object invoke = method.invoke(userServiceimpl, args);
//后置增强
System.out.println("在查询后进行增强!");
//方法返回值
return invoke+"返回值";
}
});
String allUsers = userService.findAllUsers();
System.out.println(allUsers);
}
}