相信大家都知道,有23种代理模式,其中用得比较多的或者是面试中估计问的最多的就是动态代理,但是我们知道,动态代理,静态代理都只是23种设计模式中的代理模式。好了,话不多说,直接上干货。
代理模式
1、动态代理
先创建接口:
/** * 功能描述 * * @author yaoqihui * @version 2021/7/4 * @see [相关类/方法] * @since [malan-rabbitmq] */ public interface UserService { void saveUser(); }
写一个类,实现接口:
import com.sailmalan.malan.service.UserService; import lombok.extern.slf4j.Slf4j; /** * 功能描述 * * @author yaoqihui * @version 2021/7/4 * @see [相关类/方法] * @since [malan-rabbitmq] */ @Slf4j public class UserServiceImpl implements UserService { @Override public void saveUser() { log.info("动态代理调用"); } }
创建代理类(可以重复利用)
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理类
*
* @author yaoqihui
* @version 2021/7/4
* @see [相关类/方法]
* @since [malan-rabbitmq]
*/
@Slf4j
public class InvocationHandlerImpl implements InvocationHandler {
private Object target;
public InvocationHandlerImpl(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method.invoke()方法,真正动态代理的地方,利用的是java的反射,大伙也可以看到包:java.lang.reflect.Method
return method.invoke(target, args);
}
}
动态代理测试类:
import com.sailmalan.malan.service.UserService; import com.sailmalan.malan.service.impl.UserServiceImpl; import java.lang.reflect.Proxy; /** * 功能描述:生成UserService,供调用---》类似于我们使用springBoot的注解,得到一个userService接口
@Autowired
private UserService userService; * * @author yaoqihui * @version 2021/7/4 * @see [相关类/方法] * @since [malan-rabbitmq] */
public class TestInvocationHandler {
public static void main(String[] args) {
/************************类似于达到效果的注解:
* @Autowired
* private UserService userService;
* 开始代码**************************/
UserService userService = new UserServiceImpl();
InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(userService);
ClassLoader loader = userService.getClass().getClassLoader();
Class<?>[] interfaces = userService.getClass().getInterfaces();
UserService newProxyInstance = (UserService) Proxy.newProxyInstance(loader, interfaces, invocationHandler);
/************************结束代码**************************/
newProxyInstance.saveUser();
}
}
2、CGLIB静态代理
- CGLIB动态代理和jdk代理一样,使用反射完成代理,不同的是他可以直接代理类(jdk动态代理不行,他必须目标业务类必须实现接口),CGLIB动态代理底层使用字节码技术,CGLIB动态代理不能对 final类进行继承。(CGLIB动态代理需要导入jar包)
//接口 public interface UserDao { void save(); }
//接口实现类 public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存数据方法"); } }
代理类:
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; //代理主要类 public class CglibProxy implements MethodInterceptor { private Object targetObject; // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理 public Object getInstance(Object target) { // 设置需要创建子类的类 this.targetObject = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } //代理实际方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开启事物"); Object result = proxy.invoke(targetObject, args); System.out.println("关闭事物"); // 返回代理对象 return result; } }
测试:
//测试CGLIB动态代理 public class Test { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl()); userDao.save(); } }
2、静态代理代码演示
创建UserDao类:
//接口类 public class UserDao{ public void save() { System.out.println("保存数据方法"); } }
添加代理类
//代理类 public class UserDaoProxy extends UserDao { private UserDao userDao; //此处是构造器注入 public UserDaoProxy(UserDao userDao) { this.userDao = userDao; } public void save() { System.out.println("开启事物..."); userDao.save(); System.out.println("关闭事物..."); } }
下面测试静态代理的类:
//添加完静态代理的测试类 public class Test{ public static void main(String[] args) { UserDao userDao = new UserDao(); UserDaoProxy userDaoProxy = new UserDaoProxy(userDao); userDaoProxy.save(); } }