关于Java中的代理
静态代理
在静态代理中,所有方法的增强都是我们自己手动完成的,并且接口一旦新增了方法目标对象和代理对象都需要进行修改,实际开发中一般是不会使用静态代理的,因为静态代理的实现机制来说,其在编译时就将接口、实现类、代理类这些都处理好,编译成了class文件。
代理实现步骤:
1 声明一个接口
在这里用信来举例,首先声明一个东西叫做信。
/**
* @Description: 信的接口
* @author: Kowk
*/
public interface SmsService {
String send(String message);
}
2 实现接口
刚刚声明了一个类型叫信,现在就是去写一封信,也叫接口的实现。
/**
* @Description: 类似一个动作:去写了一封信
* @author: Kowk
*/
public class SmsServiceImpl implements SmsService{
@Override
public String send(String message) {
System.out.println("发送消息"+message);
return message;
}
}
3 使用代理来调用接口
相当于一个邮差,帮你送你写好的信,并且你还可以让他在送信的前后帮忙干一些事情。
/**
* @Description: 在调用方法的前后都可以添加需要的操作
* @author: Kowk
*/
public class SmsProxy implements SmsService{
private final SmsService smsService;
public SmsProxy(SmsService smsService) {
this.smsService = smsService;
}
@Override
public String send(String message) {
//在调用实际的方法之前,添加对应的操作
System.out.println("发送之前添加任意操作");
smsService.send(message);
//在实际的方法运行结束后,还可以再次添加对应的操作
System.out.println("发送完毕之后添加任意操作");
return null; }
}
这样就实现了一次简单的静态代理。
测试代码
@Test
public void t(){
SmsService smsService = new SmsServiceImpl();
SmsProxy smsProxy = new SmsProxy(smsService);
smsProxy.send("静态代理");
}
运行结果
动态代理
JDK动态代理
JDK动态代理中核心类有两个:InvocationHandler和Proxy。
他是通过Proxy中的newProxyInstance来创建一个实例,在使用这个方法的时候就会调用InvocationHandler中的invoke进行调用。
1 创建接口和实现接口
这一步是和静态一样
2 自定义InvocationHandler
/**
* @Description: 自定义调用过程
* @author: Kowk
*/
public class SmsInvocationHandler implements InvocationHandler {
private final Object target;
public SmsInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用实际方法之前添加任意操作
System.out.println("调用之前执行相应操作");
Object res = method.invoke(target, args);
//调用实际方法之后添加任意擦欧洲哦
System.out.println("调用之后执行相应操作");
return res;
}
}
在下面Proxy新建实例中最后实际调用的是invoke中的方法。
获取需要代理的对象的工厂类
/**
* @Description: 获取代理对象来调用
* @author: Kowk
*/
public class JdkProxyFactory {
public static Object getProxy(Object target){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), //需要加载的类加载器
target.getClass().getInterfaces(),//代理需要实现的接口,可以指定多个需要实现的接口
new SmsInvocationHandler(target)//代理对象自定义的调用invoke方法
);
}
}
通过Proxy新建一个实例
最终调用
@Test
public void t(){
SmsService target = new SmsServiceImpl();
SmsService smsService = (SmsService) JdkProxyFactory.getProxy(target);
smsService.send("动态代理");
}
结果:
JDK的动态代理只能代理实现了接口的类,如果需要代理没有实现接口的类的话需要使用CGLIB进行代理,但是通常是JDK动态代理的性能更好。
关于CGLIB动态代理有机会会进行补全,如有需要可先自行查阅。
由于才疏学浅,难免有错漏之处,还望不吝赐教。
本文地址转载请注明:https://blog.csdn.net/elapse_/article/details/122612980