日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

jdk动态代理与cglib动态代理例子

發(fā)布時(shí)間:2024/4/14 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jdk动态代理与cglib动态代理例子 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.JAVA的動(dòng)態(tài)代理特征:特征是代理類(lèi)與委托類(lèi)有同樣的接口,代理類(lèi)主要負(fù)責(zé)為委托類(lèi)預(yù)處理消息、過(guò)濾消息、把消息轉(zhuǎn)發(fā)給委托類(lèi),以及事后處理消息等。代理類(lèi)與委托類(lèi)之間通常會(huì)存在關(guān)聯(lián)關(guān)系,一個(gè)代理類(lèi)的對(duì)象與一個(gè)委托類(lèi)的對(duì)象關(guān)聯(lián),代理類(lèi)的對(duì)象本身并不真正實(shí)現(xiàn)服務(wù),而是通過(guò)調(diào)用委托類(lèi)的對(duì)象的相關(guān)方法,來(lái)提供特定的服務(wù)。

它是在運(yùn)行是生成的class對(duì)象,在生成時(shí)必須提供一組或一個(gè)interface給它,然后該class就宣稱(chēng)它實(shí)現(xiàn)了這些interface。你當(dāng)然可以把該class的實(shí)例當(dāng)做這些interface中的任何一個(gè)來(lái)用,當(dāng)然,這個(gè)DynamicProxy其實(shí)就是一個(gè)Proxy,他不會(huì)替你做實(shí)質(zhì)性的工作,在生成它的實(shí)例時(shí)你必須提供一個(gè)handler,由它接管實(shí)際的工作。因此,DynamicProxy必須實(shí)現(xiàn)InvocationHandler接口。
5) 一個(gè)動(dòng)態(tài)代理了和一個(gè)InvocationHandler 實(shí)現(xiàn)關(guān)聯(lián)的。每一個(gè)動(dòng)態(tài)代理實(shí)例的調(diào)用都要通過(guò)InvocationHandler接口的handler(調(diào)用處理器)來(lái)調(diào)用,動(dòng)態(tài)代理不做任何執(zhí)行操作,只是在創(chuàng)建動(dòng)態(tài)代理時(shí),把要實(shí)現(xiàn)的接口和handler關(guān)聯(lián),動(dòng)態(tài)代理要幫助被代理執(zhí)行的任務(wù),要轉(zhuǎn)交給handler來(lái)執(zhí)行。其實(shí)就是調(diào)用invoke方法

動(dòng)態(tài)代理:在程序運(yùn)行時(shí),運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成

2.實(shí)用動(dòng)態(tài)代理步驟:

A. 創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類(lèi),他必須實(shí)現(xiàn)invoke方法
B. 創(chuàng)建被代理的類(lèi)以及接口。
C. 通過(guò)Proxy的靜態(tài)方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)創(chuàng)建一個(gè)代理
D. 通過(guò)代理調(diào)用方法

?

3.jdk動(dòng)態(tài)代理例子:

文件列表:

業(yè)務(wù)接口:UserService

業(yè)務(wù)實(shí)現(xiàn):UserServiceImpl

代理類(lèi)的調(diào)用Handler實(shí)現(xiàn):ProxyHandler

JUnit測(cè)試類(lèi):SpringProxyTest

package com.niewj.service;

import com.niewj.model.User;

public class UserServiceImpl implements UserService {

?@Override
?public void add(User user) {
??System.out.println("User Saved. & ");
?}

?@Override
?public void delete(User user) {
??System.out.println("User Deleted. &");
?}
}

?

package com.niewj.service;

import com.niewj.model.User;

public class UserServiceImpl implements UserService {

?@Override
?public void add(User user) {
??System.out.println("User Saved. & ");
?}

?@Override
?public void delete(User user) {
??System.out.println("User Deleted. &");
?}
}

?

package com.niewj.service;

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

/**
?* JDK動(dòng)態(tài)代理模擬
?*
?* 1.首先明確什么是目標(biāo)對(duì)象target,什么是代理對(duì)象proxy!!
?*
?* 2.每個(gè)代理對(duì)象對(duì)象都會(huì)有一個(gè)相關(guān)的InvocationHandler對(duì)象。
?* 當(dāng)代理對(duì)象生成的時(shí)候,是創(chuàng)建的代理對(duì)象,
?* 拿著相關(guān)的這個(gè)InvocationHandler對(duì)象,去自動(dòng)調(diào)Handler類(lèi)中實(shí)現(xiàn)的invoke方法的。
?* 下面一段話(huà)來(lái)自@javadoc@
?* <p>Each proxy instance has an associated invocation handler.
?* When a method is invoked on a proxy instance, the method
?* invocation is encoded and dispatched to the <code>invoke</code>
?* method of its invocation handler.
?*
?* 3.還有就是我發(fā)現(xiàn),我的Eclipse控制臺(tái)TMD輸出的順序有誤,害的老以為我人品出了什么問(wèn)題,
?* 不知道控制臺(tái)的信息是不是不是棧式輸出的。(好繞口)
?*
?*/
public class ProxyHandler implements InvocationHandler {

?// 就是要給這個(gè)目標(biāo)類(lèi)創(chuàng)建代理對(duì)象。
?private Object target;

?// 傳遞代理目標(biāo)的實(shí)例,因?yàn)榇硖幚砥餍枰R部梢杂胹et等方法。
?public ProxyHandler(Object target) {
??this.target = target;
?}

?/*
? * 這個(gè)方法是給代理對(duì)象調(diào)用的。
? * 留心的是內(nèi)部的method調(diào)用的對(duì)象是目標(biāo)對(duì)象,可別寫(xiě)錯(cuò)。
? */
?@Override
?public Object invoke(Object proxy, Method method, Object[] args)
???throws Throwable {
??Object ret = null;
??// 1.調(diào)用前
??cutIntoBefore(method.getName());

??ret = method.invoke(target, args);

??// 2.調(diào)用后
??cutIntoAfter(method.getName());
??return ret;
?}

?public void cutIntoBefore(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法之前");
?}

?public void cutIntoAfter(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法完后");
?}
}

?

package com.niewj;

import java.lang.reflect.Proxy;

import org.junit.Test;

import com.niewj.model.User;
import com.niewj.service.ProxyHandler;
import com.niewj.service.UserService;
import com.niewj.service.UserServiceImpl;

public class SpringProxyTest {

?@Test
?@SuppressWarnings("rawtypes")
?public void testJDKDynamicProxy() {

??/* 1.獲取UserServiceImpl對(duì)象--目標(biāo)對(duì)象--也就是需要被代理的對(duì)象。 */
??UserService userService = new UserServiceImpl();
??// 獲取當(dāng)前類(lèi)名
??Class clazz = userService.getClass();
??/*
?? * 2.獲得代理對(duì)象。
?? * 每一個(gè)代理對(duì)象都有一個(gè)相關(guān)的InvocationHandler對(duì)象,通過(guò)這個(gè)handler對(duì)象的invoke來(lái)實(shí)現(xiàn)調(diào)用中要完成的自定義貓膩行為
?? * 。 可以使用Proxy類(lèi)和自定義的調(diào)用處理邏輯來(lái)生成一個(gè)代理對(duì)象的。
?? */
??UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
????clazz.getClassLoader(), clazz.getInterfaces(),
????new ProxyHandler(userService));
??userServiceProxy.add(new User("dotjar"));
??userServiceProxy.delete(new User("DDD"));
?}
}

?

4.cglib動(dòng)態(tài)代理

JDK實(shí)現(xiàn)動(dòng)態(tài)代理需要實(shí)現(xiàn)類(lèi)通過(guò)接口定義業(yè)務(wù)方法,對(duì)于沒(méi)有接口的類(lèi),如何實(shí)現(xiàn)動(dòng)態(tài)代理呢,這就需要CGLib了。CGLib采用了非常底層的字節(jié)碼技術(shù),其原理是通過(guò)字節(jié)碼技術(shù)為一個(gè)類(lèi)創(chuàng)建子類(lèi),并在子類(lèi)中采用方法攔截的技術(shù)攔截所有父類(lèi)方法的調(diào)用,順勢(shì)織入橫切邏輯。JDK動(dòng)態(tài)代理與CGLib動(dòng)態(tài)代理均是實(shí)現(xiàn)Spring AOP的基礎(chǔ)。

它的運(yùn)行速度要遠(yuǎn)遠(yuǎn)快于JDKProxy動(dòng)態(tài)代理。

?

使用CGLIB需要導(dǎo)入以下兩個(gè)jar文件:

?

??? asm.jar – CGLIB的底層實(shí)現(xiàn)。

?

??? cglib.jar – CGLIB的核心jar包。

?

例子:

package com.niewj.service;

import java.lang.reflect.Method;

import com.niewj.model.User;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CgLibProxyImitation implements MethodInterceptor {

?private Enhancer enhancer = new Enhancer();

?/** 創(chuàng)建代理對(duì)象
? * @param targetClass
? * @return 返回代理對(duì)象
? */
?@SuppressWarnings("rawtypes")
?public Object getProxy(Class targetClass) {
??enhancer.setSuperclass(targetClass); //設(shè)置需要?jiǎng)?chuàng)建子類(lèi)的類(lèi)
??enhancer.setCallback(this);
??return enhancer.create(); //通過(guò)字節(jié)碼技術(shù)動(dòng)態(tài)創(chuàng)建子類(lèi)實(shí)例

?}

?public void cutIntoBefore(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法之前");
?}

?public void cutIntoAfter(String mName) {
??System.err.println("調(diào)用____" + mName + "()____方法完后");
?}

?/*? 生成的代理對(duì)象調(diào)用此對(duì)象來(lái)替代原始對(duì)象
? *
? * @java.lang.Object 增強(qiáng)對(duì)象
? * @java.lang.reflect.Method 攔截方法
? * @java.lang.Object[] 參數(shù)數(shù)組
? * @net.sf.cglib.proxy.MethodProxy? 用于調(diào)用父類(lèi),按需要調(diào)用多次
? */
?@Override
?public Object intercept(Object obj, Method method, Object[] args,
???MethodProxy proxy) throws Throwable {
??cutIntoBefore(method.getName());
??Object result = proxy.invokeSuper(obj, args);
??cutIntoAfter(method.getName());
??return result;
?}
?
?public static void main(String[] args) {
//??UserService userService = new UserServiceImpl();
??CgLibProxyImitation cglib = new CgLibProxyImitation();
??UserServiceImpl userService = (UserServiceImpl)cglib.getProxy(UserServiceImpl.class);
??userService.add(new User("dotjar"));
??userService.delete(new User("hill"));
?}
}

?

總結(jié)

以上是生活随笔為你收集整理的jdk动态代理与cglib动态代理例子的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。