代理模式是当我们要调用某个目标方法时,不直接调用这个方法,而是通过调用某个代理类中的方法来实现目标方法调用;这样就可以在调用目标方法前后执行一些特定方法,来实现目标方法的增强。
代理模式可以分为静态代理和动态代理两种,静态代理就是在编码时已经确认了委托类和代理类的关系;动态代理是使用反射和字节码的技术,在运行期创建指定接口或类的子类,以及实例对象的技术。
在java中实现代理有两种技术:如果目标类实现了接口,就可以使用JDK中的Proxy实现动态代理;如果目标类没有实现接口,需要使用cglib实现代理,cglib是基于ASM的字节码生成库,允许在运行时对字节码进行修改和动态生成。
下面演示这两种方式实现的代理:
工程中需要引入cglib项目坐标,如果项目中使用了spring框架,就不需要这个项目坐标,因为在spring中已经集成了cglib项目。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
下面的是目标类和它对应的接口:
/**
* @createDate: 2023/6/29
*/
public interface MyTarget {
/**
* 目标方法执行
*/
void runMethod();
}
/**
* @createDate: 2023/6/29
*/
public class MyTargetImpl implements MyTarget {
@Override
public void runMethod() {
System.out.println("目标类方法执行....");
}
}
增强类和对应的方法如下,希望在执行目标类中的方法前后分别执行对应增强类中的方法:
/**
* @createDate: 2023/6/29
*/
public class MyAdvice {
public void before() {
System.out.println("前置方法执行....");
}
public void after() {
System.out.println("后置方法执行....");
}
}
接下来演示分别使用proxy和cglib两种代理方式实现的动态代理:
使用jdk中的Proxy代理实现代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @createDate: 2023/6/29
*/
public class ProxyTest {
public static void main(String[] args) {
// 实例化对象
MyAdvice myAdvice = new MyAdvice();
MyTargetImpl myTarget = new MyTargetImpl();
// 构建代理对象
final Object proxy = Proxy.newProxyInstance(myTarget.getClass().getClassLoader(), myTarget.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
myAdvice.before();
final Object result = method.invoke(myTarget, args);
myAdvice.after();
return result;
}
});
// 强转为实现类的接口,并执行方法
MyTarget proxyObj = (MyTarget) proxy;
proxyObj.runMethod();
}
}
使用cglib代理实现代码如下:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @createDate: 2023/6/29
*/
public class CglibTest {
public static void main(String[] args) {
// 实例化对象
MyAdvice myAdvice = new MyAdvice();
MyTargetImpl myTarget = new MyTargetImpl();
Enhancer enhancer = new Enhancer();
// 设置父类,这样生成的代理对象就是这个类的子类
enhancer.setSuperclass(MyTargetImpl.class);
// 设置回调,这样执行代理对象的方法时最终就会调用到这里的方法
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
myAdvice.before();
final Object invoke = method.invoke(myTarget, objects);
myAdvice.after();
return invoke;
}
});
final MyTargetImpl proxy = (MyTargetImpl) enhancer.create();
proxy.runMethod();
}
}
上面就演示了两种使用代理模式的代码,虽然比较简单却演示了在框架中实现代理类的原理,只不过框架中会通过配置文件方式或注解标签方式更灵活的实现代理功能,但是翻看源码,最后都会走到如上的代理代码。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181869.html