静态代理与JDK、CGLib动态代理
一、代理模式
代理模式概述
代理模式是设计模式之一,代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者执行功能时会附加一些额外的操作。符合开闭原则,不用修改被代理者任何的代码,就能扩展新的功能。
分类
代理分为静态代理和动态代理
静态代理
静态代理是字节码一上来就创建好,并完成加载。
1.代理者和被代理者都实现了相同的接口(或继承相同的父类)
2.代理者包含了一个被代理者的对象
3.调用功能时,代理者会调用被代理者的功能,同时附加新的操作动态代理
动态代理
字节码随用随创建,随用随加载。不修改源码的基础上对方法增强
动态代理又分为:JDK动态代理和CGLib动态代理
区别是:
JDK动态代理的被代理者必须实现任意接口
CGLib动态代理不用实现接口,是通过继承实现的
二、静态代理
1.准备被代理的类
public interface IUserService {
void save();
void select(Long id);
}
public class UserService implements IUserService {
@Override
public void save() {
System.out.println("save....");
}
@Override
public void select(Long id) {
System.out.println("select..."+id);
}
}
2.编写静态代理
public class StaticProxy implements IUserService {
UserService userService;
public StaticProxy(UserService userService){
this.userService=userService;
}
@Override
public void save() {
System.out.println("开始执行save()方法....");
userService.save();
System.out.println("save()方法执行结束....");
}
@Override
public void select(Long id) {
}
}
3.执行测试
public class StaticProxyTest {
@Test
public void test(){
UserService userService = new UserService();
StaticProxy staticProxy = new StaticProxy(userService);
staticProxy.save();
}
}
三、基于接口的JDK动态代理
使用JDK 官方的 Proxy 类。要求被代理类最少实现一个接口。
JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理.
需要指定一个类加载器,然后生成的代理对象实现类的接口或类的类型,接着处理额外功能
1.准备被代理的类
public interface IUserService {
void save();
void select(Long id);
}
public class UserService implements IUserService {
@Override
public void save() {
System.out.println("save....");
}
@Override
public void select(Long id) {
System.out.println("select..."+id);
}
}
2.编写基Proxy动态代理
方式一:
public class InterfaceProxy {
final UserService userService=new UserService();
/**
* 使用Proxy类中的newProxyInstance方法创建代理对象
*
* 创建代理对象的要求被代理类最少实现一个接口
*
* newProxyInstance方法的参数:
* ClassLoader:类加载器,用于加载代理对象字节码。和被代理对象使用相同的类加载器。
* Class[]:字节码数组,用于让代理对象和被代理对象有相同方法。
* InvocationHandler:用于提供增强的代码,写如何代理。一般是写该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
*
*/
IUserService iUserServiceProxy= (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), UserService.class.getInterfaces(), new InvocationHandler() {
/**
* 执行被代理对象的任何接口方法都会经过该方法
*
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @return 和被代理对象方法有相同的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-------------------------------");
System.out.println("进入动态代理类。。。。。。。。");
Object returnValue = null;
//对select方法作增强
if("select".equals(method.getName())) {
//获取参数
Long id = (Long) args[0];
//让id+10
id+=10;
returnValue = method.invoke(userService, id);
}
return returnValue;
}
});
}
方式二:
public class InterfaceProxy implements InvocationHandler {
private Object object;
public InterfaceProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("-------------------------------");
System.out.println("进入动态代理类。。。。。。。。");
Object returnValue = null;
//对select方法作增强
if("select".equals(method.getName())) {
//获取参数
Long id = (Long) objects[0];
//让id+10
id+=10;
returnValue = method.invoke(object, id);
}
return returnValue;
}
}
3.执行测试
执行测试一:
public class ProxyTest {
@Test
public void Test(){
InterfaceProxy interfaceProxy = new InterfaceProxy();
//未代理
interfaceProxy.userService.select(1L);
//经过代理
interfaceProxy.iUserServiceProxy.select(1L);
}
}
public class ProxyTest {
@Test
public void Test() {
UserServiceuserService = new UserService();
InterfaceProxy interfaceProxy = new InterfaceProxy(userService);
IUserService iUserServiceProxy= (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), UserService.class.getInterfaces(),interfaceProxy);
//未代理
userService.select(1L);
//经过代理
iUserServiceProxy.select(1L);
}
}
四、基于子类的CGLib动态代理
使用第三方的 CGLib。要求被代理类不能用 final 修饰。
Cglib是动态代理利用asm的开源包,对代理对象的Class文件加载进来,通过修改其字节码生成的子类来处理Cglib是基于继承父类生成的代理类.
1.准备被代理的类
public interface IUserService {
void save();
void select(Long id);
}
public class UserService implements IUserService {
@Override
public void save() {
System.out.println("save....");
}
@Override
public void select(Long id) {
System.out.println("select..."+id);
}
public void cglibTest(String string){
System.out.println(string);
}
}
2.编写Cglib动态代理
方式一:
public class SonCglib{
final UserService userService=new UserService();
/**
* 使用Enhancer类中的create方法创建代理对象
*
* 创建代理对象要求被代理类不能是最终类
*
* create方法的参数:
* Class:字节码,用于指定被代理对象的字节码。
*
* Callback:用于提供增强的代码,写如何代理。一般是写该接口的实现类,通常情况下是匿名内部类,但不是必须的。
*/
UserService userServiceCglib = (UserService) Enhancer.create(userService.getClass(), new MethodInterceptor() {
/**
* 执行被代理对象的任何接口方法都会经过该方法
*
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @param methodProxy :当前执行方法的代理对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("-------------------------------");
System.out.println("进入动态代理类。。。。。。。。");
Object returnValue = null;
//对cglibTest方法增强
if("cglibTest".equals(method.getName())) {
//获取参数
String str = (String) args[0];
//对参数做点改变
str+="____World!";
returnValue = method.invoke(userService, str);
}
return returnValue;
}
});
}
方式二:
public class SonCglib implements MethodInterceptor {
/**
* 获取代理对象
* @param object 被代理对象
* @return 代理对象
*/
public Object createProxy(Object object){
//得到Enhancer类中实例
Enhancer eh = new Enhancer();
//设置被代理对象的类为父类
eh.setSuperclass(object.getClass());
//设置代理对象的回调
eh.setCallback(this);
//创建代理对象
return eh.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("-------------------------------");
System.out.println("进入动态代理类。。。。。。。。");
Object returnValue = null;
//对cglibTest方法增强
if("cglibTest".equals(method.getName())) {
//获取参数
String str = (String) objects[0];
//对参数做点改变
str+="____World!";
objects[0]=str;
returnValue = methodProxy.invokeSuper(o,objects);
}
return returnValue;
}
}
3.执行测试
方式一:
public class CglibTest {
@Test
public void test(){
SonCglib sonCglib = new SonCglib();
//未被动态代理
sonCglib.userService.select(1L);
sonCglib.userService.cglibTest("Hello ");
//基于子类的动态代理
sonCglib.userServiceCglib.select(1L);
sonCglib.userServiceCglib.cglibTest("Hello ");
}
}
public class CglibTest {
@Test
public void test(){
SonCglib cglib = new SonCglib();
UserService userService = (UserService) cglib.createProxy(new UserService());
userService.cglibTest("Hello ");
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137135.html