当前位置: 代码迷 >> 综合 >> 静态代理-动态代理(JDK/CGLib)
  详细解决方案

静态代理-动态代理(JDK/CGLib)

热度:27   发布时间:2024-03-09 23:07:00.0

1、代理模式简介

  • 代理模式好比帮你处理其他琐碎事情的类,比如小明要结婚,那他可以找个婚庆公司帮助他干一些布置婚礼现场,婚礼前的一些准备,和婚礼后的一些准备,而婚庆公司就相当于一个代理!
  • 说白了就是相当于一个代理对象帮你添加额外的功能,比如说加日志,加事务等!

2、代理模式的分类

  • 静态代理
  • 动态代理

3、静态代理

public class Demo_07 {
    public static void main(String[] args) {
    // 创建一个真实对象 人You you = new You();// 创建一个代理对象 婚庆公司WeddingCompany weddingCompany = new WeddingCompany(you);weddingCompany.HappyMarry();}
}// 结婚的接口
interface Marrry {
    void HappyMarry();
}class You implements Marrry {
    @Overridepublic void HappyMarry() {
    System.out.println("田老师要结婚了!");}
}//婚庆公司 相当于一个静态代理
class WeddingCompany implements Marrry {
    private You you = null;public WeddingCompany(You you) {
    this.you = you;}@Overridepublic void HappyMarry() {
    before();you.HappyMarry();after();}public static void before() {
    System.out.println("结婚之前布置现场");}public static void after() {
    System.out.println("结婚之后收尾款");}
}

4、动态代理

4.1、JDK动态代理

  1. 编写代理

    public class UserHandle implements InvocationHandler {
          private Object targetObject;// 获取代理类public Object newProxyInstance(Object targetObject) {
          System.out.println("proxy" + targetObject);this.targetObject = targetObject;return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);}// 添加额外操作@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          Object ret = null;System.out.println("正在进行操作前的准备----");ret = method.invoke(targetObject, args);System.out.println("操作成功!");return ret;}
    }
    
  2. 测试

    @Test
    public void addTest() {
          User user = new User();user.setUsername("动态代理!");// 要代理对象UserService userService = new UserServiceImpl();// 获取代理对象UserHandle userHandle = new UserHandle();UserService userServiceProxy = (UserService) userHandle.newProxyInstance(userService);// 代理对象调用真实方法userServiceProxy.addUser(user);
    }
    

4.2、CGLib动态代理

  1. 创建代理

    public class UserCGlibHandle implements MethodInterceptor {
          private Object targetObject;// 获取目标对象public UserCGlibHandle(Object targetObject) {
          this.targetObject = targetObject;}// 获取代理类public Object createProxy() {
          //字节码增强技术Enhancer enhancer = new Enhancer();//设置代理类的父类是目标类enhancer.setSuperclass(targetObject.getClass());//设置回调enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
          Object ret = null;// 编写自己要添加的业务// 增删改需要开始事务if (method.getName().equals("insertUser") ||method.getName().equals("deleteUser") ||method.getName().equals("updateUser")) {
          System.out.println("假装开启了事务");ret = method.invoke(this.targetObject, args);System.out.println("假装提交了事务");} else {
          ret = method.invoke(this.targetObject, args);}return ret;}
    }
    
  2. 测试

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration({
          "classpath:applicationContext.xml"})
    public class UserHandleTest {
          @Autowiredprivate UserService userService;@Testpublic void cgLibTest() {
          UserCGlibHandle userCGlibHandle = new UserCGlibHandle(userService);UserService userServiceProxy = (UserService) userCGlibHandle.createProxy();int i = userServiceProxy.deleteUser(2);System.out.println(i);List<User> users = userServiceProxy.selectByAll();for (User user : users) {
          System.out.println(user);}}
    }
    

小结:

  • CGlib动态代理可以代理实现类!

  • JDK动态代理只能代理接口!

5、小结

  • 静态代理通常只代理一个类,动态代理会代理接口中的实现类!
  • 静态代理在编译的时候就知道了要代理谁,动态代理在运行的时候才知道要代理谁!
  • spring aop即使用了动态代理,也使用了静态代理!