java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring AOP静态代理和动态代理

Spring AOP里的静态代理和动态代理用法详解

作者:陈彦斌

这篇文章主要介绍了 Spring AOP里的静态代理和动态代理用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

什么是代理?

  为某一个对象创建一个代理对象,程序不直接用原本的对象,而是由创建的代理对象来控制原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间

什么是静态代理?

  由程序创建或特定工具自动生成源代码,在程序运行前,代理类的.class文件就已经存在

  通过将目标类与代理类实现同一个接口,让代理类持有真实类对象,然后在代理类方法中调用真实类方法,在调用真实类方法的前后添加我们所需要的功能扩展代码来达到增强的目的。

优点

缺点

案例演示

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回调
  * @param outTradeNo 订单号
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下单
  * @param userId 用户id
  * @param productId 产品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口实现类)

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目标类 PayServiceImpl 回调 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目标类 PayServiceImpl 回调 方法 save");
  return productId;
 }
}

StaticProxyPayServiceImpl.java(接口实现类,静态代理)

package net.cybclass.sp.proxy;

public class StaticProxyPayServiceImpl implements PayService{
 private PayService payService;
 public StaticProxyPayServiceImpl(PayService payService)
 {
  this.payService=payService;
 }
 public String callback(String outTradeNo) {
  System.out.println("StaticProxyPayServiceImpl callback begin");
  String result=payService.callback(outTradeNo);
  System.out.println("StaticProxyPayServiceImpl callback end");
  return result;
 }

 public int save(int userId, int productId) {
  System.out.println("StaticProxyPayServiceImpl save begin");
  int id = payService.save(userId, productId);
  System.out.println("StaticProxyPayServiceImpl save end");
  return id;
 }
}

演示

什么是动态代理?

  在程序运行时,运用反射机制动态创建而成,无需手动编写代码

JDK动态代理

CGLIB动态代理(原理:是对指定的业务类生成一个子类,并覆盖其中的业务方法来实现代理)

jdk动态代理演示

定义一个类,去实现InvocationHandler这个接口,并车从写invoke方法

//Object proxy:被代理的对象
//Method method:要调用的方法
//Object[] args:方法调用时所需要参数
public Object invoke(Object proxy, Method method, Object[] args){}

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回调
  * @param outTradeNo 订单号
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下单
  * @param userId 用户id
  * @param productId 产品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口实现类)

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目标类 PayServiceImpl 回调 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目标类 PayServiceImpl 回调 方法 save");
  return productId;
 }
}

JDKProxy.java(jdk动态代理类)

package net.cybclass.sp.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy implements InvocationHandler {
 //目标类
 private Object targetObject;

 /**
  * 获取代理对象
  * @param targetObject 目标类
  * @return
  */
 public Object newProxyInstance(Object targetObject) {
  this.targetObject = targetObject;
  //绑定关系,也就是和具体的那个实现类关联
  return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
    targetObject.getClass().getInterfaces(), this);
 }

 /**
  * JDK动态代理
  *
  * @param proxy 静态代理对象
  * @param method 要调用的方法
  * @param args 方法调用时所需要参数
  * @return
  * @throws Throwable
  */
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Object result = null;
  try {
   System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 begin");
   result = method.invoke(targetObject, args);
   System.out.println("通过JDK动态代理调用"+method.getName()+",打印日志 end");
  } catch (Exception ex) {
   ex.printStackTrace();
  }
  return result;
 }
}

CGLIB动态代理演示

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回调
  * @param outTradeNo 订单号
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下单
  * @param userId 用户id
  * @param productId 产品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口实现类)

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目标类 PayServiceImpl 回调 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目标类 PayServiceImpl 回调 方法 save");
  return productId;
 }
}

CGLIBProxy.java(CGLIB动态代理类)

package net.cybclass.sp.proxy;

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;
 //绑定关系
 public Object newProxyInstance(Object targetObject){
  this.targetObject=targetObject;
  Enhancer enhancer=new Enhancer();
  //设置代理类的父类(目标类)
  enhancer.setSuperclass(this.targetObject.getClass());
  //设置回调函数
  enhancer.setCallback(this);
  //创建子类(代理对象)
  return enhancer.create();
 }
 public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  Object result=null;
  try
  {
   System.out.println("通过CGLIB动态代理调用"+method.getName()+",打印日志 begin");
   result=methodProxy.invokeSuper(o,args);
   System.out.println("通过CGLIB动态代理调用"+method.getName()+",打印日志 end");
  }
  catch (Exception ex){
   ex.printStackTrace();
  }
  return result;
 }
}

总结

  动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理,解耦和易维护。

两种动态代理的区别

Spring AOP中的代理使用的默认策略

到此这篇关于 Spring AOP里的静态代理和动态代理用法详解的文章就介绍到这了,更多相关 Spring AOP 静态代理 动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文