欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring AOP里的靜態(tài)代理和動(dòng)態(tài)代理用法詳解

 更新時(shí)間:2020年07月24日 16:36:23   作者:陳彥斌  
這篇文章主要介紹了 Spring AOP里的靜態(tài)代理和動(dòng)態(tài)代理用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

什么是代理?

  為某一個(gè)對(duì)象創(chuàng)建一個(gè)代理對(duì)象,程序不直接用原本的對(duì)象,而是由創(chuàng)建的代理對(duì)象來(lái)控制原對(duì)象,通過(guò)代理類(lèi)這中間一層,能有效控制對(duì)委托類(lèi)對(duì)象的直接訪(fǎng)問(wèn),也可以很好地隱藏和保護(hù)委托類(lèi)對(duì)象,同時(shí)也為實(shí)施不同控制策略預(yù)留了空間

什么是靜態(tài)代理?

  由程序創(chuàng)建或特定工具自動(dòng)生成源代碼,在程序運(yùn)行前,代理類(lèi)的.class文件就已經(jīng)存在

  通過(guò)將目標(biāo)類(lèi)與代理類(lèi)實(shí)現(xiàn)同一個(gè)接口,讓代理類(lèi)持有真實(shí)類(lèi)對(duì)象,然后在代理類(lèi)方法中調(diào)用真實(shí)類(lèi)方法,在調(diào)用真實(shí)類(lèi)方法的前后添加我們所需要的功能擴(kuò)展代碼來(lái)達(dá)到增強(qiáng)的目的。

優(yōu)點(diǎn)

  •   代理使客戶(hù)端不需要知道實(shí)現(xiàn)類(lèi)是什么,怎么做,而客戶(hù)端只需知道代理即可
  •   方便增加功能,擴(kuò)展業(yè)務(wù)邏輯

缺點(diǎn)

  •   代理類(lèi)中常出現(xiàn)大量冗余的代碼,非常不利于擴(kuò)展和維護(hù)
  •   如果接口增加一個(gè)方法,除了所有實(shí)現(xiàn)類(lèi)需要實(shí)現(xiàn)這個(gè)方法外,所有代理類(lèi)也需要實(shí)現(xiàn)此方法。增加了代碼維護(hù)的復(fù)雜度

案例演示

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回調(diào)
  * @param outTradeNo 訂單號(hào)
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下單
  * @param userId 用戶(hù)id
  * @param productId 產(chǎn)品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口實(shí)現(xiàn)類(lèi))

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 save");
  return productId;
 }
}

StaticProxyPayServiceImpl.java(接口實(shí)現(xiàn)類(lèi),靜態(tài)代理)

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;
 }
}

演示

什么是動(dòng)態(tài)代理?

  在程序運(yùn)行時(shí),運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成,無(wú)需手動(dòng)編寫(xiě)代碼

JDK動(dòng)態(tài)代理

CGLIB動(dòng)態(tài)代理(原理:是對(duì)指定的業(yè)務(wù)類(lèi)生成一個(gè)子類(lèi),并覆蓋其中的業(yè)務(wù)方法來(lái)實(shí)現(xiàn)代理)

jdk動(dòng)態(tài)代理演示

定義一個(gè)類(lèi),去實(shí)現(xiàn)InvocationHandler這個(gè)接口,并車(chē)從寫(xiě)invoke方法

//Object proxy:被代理的對(duì)象
//Method method:要調(diào)用的方法
//Object[] args:方法調(diào)用時(shí)所需要參數(shù)
public Object invoke(Object proxy, Method method, Object[] args){}

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回調(diào)
  * @param outTradeNo 訂單號(hào)
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下單
  * @param userId 用戶(hù)id
  * @param productId 產(chǎn)品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口實(shí)現(xiàn)類(lèi))

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 save");
  return productId;
 }
}

JDKProxy.java(jdk動(dòng)態(tài)代理類(lèi))

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 {
 //目標(biāo)類(lèi)
 private Object targetObject;

 /**
  * 獲取代理對(duì)象
  * @param targetObject 目標(biāo)類(lèi)
  * @return
  */
 public Object newProxyInstance(Object targetObject) {
  this.targetObject = targetObject;
  //綁定關(guān)系,也就是和具體的那個(gè)實(shí)現(xiàn)類(lèi)關(guān)聯(lián)
  return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
    targetObject.getClass().getInterfaces(), this);
 }

 /**
  * JDK動(dòng)態(tài)代理
  *
  * @param proxy 靜態(tài)代理對(duì)象
  * @param method 要調(diào)用的方法
  * @param args 方法調(diào)用時(shí)所需要參數(shù)
  * @return
  * @throws Throwable
  */
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Object result = null;
  try {
   System.out.println("通過(guò)JDK動(dòng)態(tài)代理調(diào)用"+method.getName()+",打印日志 begin");
   result = method.invoke(targetObject, args);
   System.out.println("通過(guò)JDK動(dòng)態(tài)代理調(diào)用"+method.getName()+",打印日志 end");
  } catch (Exception ex) {
   ex.printStackTrace();
  }
  return result;
 }
}

CGLIB動(dòng)態(tài)代理演示

PayService.java(接口)

package net.cybclass.sp.proxy;

public interface PayService {
 /**
  * 支付回調(diào)
  * @param outTradeNo 訂單號(hào)
  * @return
  */
 String callback(String outTradeNo);

 /**
  * 下單
  * @param userId 用戶(hù)id
  * @param productId 產(chǎn)品id
  * @return
  */
 int save(int userId,int productId);
}

PayServiceImpl.java(接口實(shí)現(xiàn)類(lèi))

package net.cybclass.sp.proxy;

public class PayServiceImpl implements PayService{
 public String callback(String outTradeNo) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 callback");
  return outTradeNo;
 }

 public int save(int userId, int productId) {
  System.out.println("目標(biāo)類(lèi) PayServiceImpl 回調(diào) 方法 save");
  return productId;
 }
}

CGLIBProxy.java(CGLIB動(dòng)態(tài)代理類(lèi))

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 {
 //目標(biāo)類(lèi)
 private Object targetObject;
 //綁定關(guān)系
 public Object newProxyInstance(Object targetObject){
  this.targetObject=targetObject;
  Enhancer enhancer=new Enhancer();
  //設(shè)置代理類(lèi)的父類(lèi)(目標(biāo)類(lèi))
  enhancer.setSuperclass(this.targetObject.getClass());
  //設(shè)置回調(diào)函數(shù)
  enhancer.setCallback(this);
  //創(chuàng)建子類(lèi)(代理對(duì)象)
  return enhancer.create();
 }
 public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  Object result=null;
  try
  {
   System.out.println("通過(guò)CGLIB動(dòng)態(tài)代理調(diào)用"+method.getName()+",打印日志 begin");
   result=methodProxy.invokeSuper(o,args);
   System.out.println("通過(guò)CGLIB動(dòng)態(tài)代理調(diào)用"+method.getName()+",打印日志 end");
  }
  catch (Exception ex){
   ex.printStackTrace();
  }
  return result;
 }
}

總結(jié)

  動(dòng)態(tài)代理與靜態(tài)代理相比較,最大的好處是接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個(gè)集中的方法中處理,解耦和易維護(hù)。

兩種動(dòng)態(tài)代理的區(qū)別

  • JDK動(dòng)態(tài)代理:要求目標(biāo)對(duì)象實(shí)現(xiàn)一個(gè)接口,但是有時(shí)候目標(biāo)對(duì)象只是一個(gè)單獨(dú)的對(duì)象,并沒(méi)有實(shí)現(xiàn)任何的接口,這個(gè)時(shí)候就可以用CGLIB動(dòng)態(tài)代理
  • JDK動(dòng)態(tài)代理是自帶的,CGLIB需要引入第三方包
  • CGLIB動(dòng)態(tài)代理,它是內(nèi)存中構(gòu)建一個(gè)子類(lèi)對(duì)象從而實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象功能的擴(kuò)展
  • CGLIB動(dòng)態(tài)代理基于繼承來(lái)實(shí)現(xiàn)代理,所以無(wú)法對(duì)final類(lèi),private方法和static方法實(shí)現(xiàn)代理

Spring AOP中的代理使用的默認(rèn)策略

  • 如果目標(biāo)對(duì)象實(shí)現(xiàn)類(lèi)接口,則默認(rèn)采用JDK動(dòng)態(tài)代理
  • 如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,則采用CGLIB進(jìn)行動(dòng)態(tài)代理

到此這篇關(guān)于 Spring AOP里的靜態(tài)代理和動(dòng)態(tài)代理用法詳解的文章就介紹到這了,更多相關(guān) Spring AOP 靜態(tài)代理 動(dòng)態(tài)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論