国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

淺入淺出Java代理的三種實(shí)現(xiàn)

lewif / 3218人閱讀

摘要:代理模式的實(shí)現(xiàn)靜態(tài)代理優(yōu)缺點(diǎn)優(yōu)點(diǎn)只對(duì)對(duì)需要的方法加代理邏輯。通過(guò)繼承的方式進(jìn)行代理,無(wú)論目標(biāo)對(duì)象有沒(méi)有實(shí)現(xiàn)接口都可以代理,但是無(wú)法處理的情況。

注意:本文所有的class使用的static修飾主要是為了能在一個(gè)類里面測(cè)試。實(shí)際項(xiàng)目中不應(yīng)該這樣做的,應(yīng)該分包分class。
文字描述不是很多,還是看代碼比較好理解吧...

1. Java代理的理解

代理模式是一種設(shè)計(jì)模式,簡(jiǎn)單說(shuō)即是在不改變?cè)创a的情況下,實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的功能擴(kuò)展。
使用場(chǎng)景:如在方法執(zhí)行前后計(jì)算執(zhí)行時(shí)間,記錄日志等。在不改變?cè)a的條件下實(shí)現(xiàn)這些功能的擴(kuò)展。

2. 代理模式的實(shí)現(xiàn) 2.1 靜態(tài)代理 2.1.0 優(yōu)缺點(diǎn)

優(yōu)點(diǎn): 只對(duì)對(duì)需要的方法加代理邏輯。

缺點(diǎn): 1.每次代理都需要實(shí)現(xiàn)一個(gè)代理類;2. 代理類功能固定,無(wú)法靈活改變。3. 項(xiàng)目會(huì)有一大批代理的代碼,如果目標(biāo)對(duì)象改變,代理類也需要對(duì)應(yīng)改變,不利于代碼的維護(hù)。

2.1.1 實(shí)現(xiàn)方式一:繼承代理(繼承方式實(shí)現(xiàn)代理)
public class StaticProxyByExtendTest {

    //目標(biāo)對(duì)象
    public static class UserServiceImpl {
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
    }
    
    //代理對(duì)象
    public static class UserServiceImplProxy extends UserServiceImpl{
        public void login(String username, String pwd) {
            System.out.println("before.... ");//代理額外邏輯
            super.login(username, pwd);//調(diào)用原實(shí)現(xiàn)方法
            System.out.println("after.... ");//代理額外邏輯
        }
    }

    //測(cè)試
    public static void main(String[] args) {
        UserServiceImpl ee = new UserServiceImplProxy();
        ee.login("Stephen", "123");
    }

}
2.1.2 實(shí)現(xiàn)方式二:聚合方式(通過(guò)實(shí)現(xiàn)相同接口)
public class StaticProxyByGroupTest {

    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標(biāo)對(duì)象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對(duì)象
    public static class UserServiceImplProxy implements UserService {

        private UserService userService;
        
        public UserServiceImplProxy(UserService userService) {
            this.userService = userService;
        }
        
        @Override
        public void login(String username, String pwd) {
            System.out.println("before.... ");//代理額外邏輯
            userService.login(username, pwd);//調(diào)用原實(shí)現(xiàn)方法
            System.out.println("after.... ");//代理額外邏輯
        }
        
    }
    
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        UserService tt = new UserServiceImplProxy(target);
        tt.login("Stephen", "123");
    }

}

使用聚合方式我們還可以添加其他的代理對(duì)象來(lái)對(duì)已經(jīng)代理的對(duì)象繼續(xù)做增強(qiáng)代理。

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

JDK原生動(dòng)態(tài)代理是Java原生支持的,不需要任何外部依賴,但是它只能基于接口進(jìn)行代理;

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

優(yōu)點(diǎn): 動(dòng)態(tài)代理所有接口。

缺點(diǎn): 必須依賴使用接口方式來(lái)實(shí)現(xiàn)代理。

主要實(shí)現(xiàn)是使用JDK自帶的Proxy類來(lái)實(shí)現(xiàn)

newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

動(dòng)態(tài)代理不需要對(duì)方法逐一實(shí)現(xiàn)代理,通過(guò)反射循環(huán)所有的接口方法,統(tǒng)一動(dòng)態(tài)的加上代理邏輯。我們也可以通過(guò)執(zhí)行方法的名字來(lái)過(guò)濾當(dāng)前方法是否需要代理。

2.2.1 基本實(shí)現(xiàn)方式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyByJDKTest {
    
    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標(biāo)對(duì)象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對(duì)象1
    public static class UserServiceImplProxy {

        private UserService userServiceProxy;
        
        public UserServiceImplProxy(UserService userService) {
        //通過(guò)JDK動(dòng)態(tài)代理獲取UserService的代理對(duì)象
            UserService proxy = (UserService) Proxy.newProxyInstance(
                    userService.getClass().getClassLoader(), //1. 類加載器
                    userService.getClass().getInterfaces(), // 2. 代理需要實(shí)現(xiàn)的接口,可以有多個(gè)
                    new InvocationHandler() { // 3. 方法調(diào)用的實(shí)際處理者

                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("before.... ");//代理額外邏輯
                            Object returnValue = method.invoke(userService, args);
                            System.out.println("after.... ");//代理額外邏輯
                            return returnValue;
                        }
                        
                    });
            
            this.userServiceProxy = proxy;
        }

        public UserService getProxy() {
            return this.userServiceProxy;
        }
        
    }
    
    //獲取動(dòng)態(tài)代理對(duì)象的公共方法
    @SuppressWarnings("unchecked")
    public static  T getJDKProxy(T t) {
        T proxy = (T) Proxy.newProxyInstance(
                t.getClass().getClassLoader(), 
                t.getClass().getInterfaces(), 
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before.... ");//代理額外邏輯
                        Object returnValue = method.invoke(t, args);
                        System.out.println("after.... ");//代理額外邏輯
                        return returnValue;
                    }
                    
                });
        
        return proxy;
    }

    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        //代理對(duì)象1
        UserServiceImplProxy proxy = new UserServiceImplProxy(target);
        proxy.getProxy().login("Stephen", "123");
        
        //代理對(duì)象
        UserService jdkProxy = getJDKProxy(target);
        jdkProxy.login("JDK Stephen", "123");
    }

}
2.2.2 優(yōu)化動(dòng)態(tài)代理

JDK Proxy動(dòng)態(tài)代理進(jìn)一步優(yōu)化:

抽象出代理父類

代理類實(shí)現(xiàn)自己的before和after方法

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

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

public class DynamicProxyByJDKTest2 {
    //目標(biāo)接口
    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標(biāo)對(duì)象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對(duì)象
    public static class UserServiceImplProxy extends JDKProxy {
        
        public UserService userServiceProxy;

        public UserServiceImplProxy(UserService userService) {
            this.userServiceProxy = getJDKProxy(userService);
        }
        
        @Override
        protected void before(Method method) {
            System.out.println("before.... ");//代理額外邏輯
        }

        @Override
        protected void after(Method method) {
            System.out.println("after.... ");//代理額外邏輯
        }

    }
    
    //Common proxy object class
    public static abstract class JDKProxy {
        
        protected abstract void before(Method method);
        
        protected abstract void after(Method method);
        
        @SuppressWarnings("unchecked")
        protected  T getJDKProxy(T t) {
            T proxy = (T) Proxy.newProxyInstance(
                    t.getClass().getClassLoader(), 
                    t.getClass().getInterfaces(), 
                    new InvocationHandler() {

                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            before(method);//代理額外邏輯
                            Object returnValue = method.invoke(t, args);
                            after(method);//代理額外邏輯
                            return returnValue;
                        }
                        
                    });
            
            return proxy;
        }
    }
    
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        //代理對(duì)象
        UserServiceImplProxy proxy = new UserServiceImplProxy(target);
        proxy.userServiceProxy.login("Stephen", "123");
    }

}
2.3 Cglib代理

CGLIB(Code Generation Library)是一個(gè)基于ASM的字節(jié)碼生成庫(kù),它允許我們?cè)谶\(yùn)行時(shí)對(duì)字節(jié)碼進(jìn)行修改和動(dòng)態(tài)生成。
CGLIB通過(guò)繼承的方式進(jìn)行代理,無(wú)論目標(biāo)對(duì)象有沒(méi)有實(shí)現(xiàn)接口都可以代理,但是無(wú)法處理final的情況。

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

優(yōu)點(diǎn):Cglib代理不依賴接口,JDK代理賴接口

缺點(diǎn):

在Spring的AOP編程中:

如果加入容器的目標(biāo)對(duì)象有實(shí)現(xiàn)接口,用JDK代理

如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,用Cglib代理

2.3.1 使用spring-core實(shí)現(xiàn)cglib代理

需要引用spring-core.jarSpring Core ? 5.1.8.RELEASE

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class DynamicProxyBySpringCglibTest {

    //目標(biāo)接口
    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標(biāo)對(duì)象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對(duì)象
    public static class ProxyFactory implements MethodInterceptor {

        private Object target;
        
        public ProxyFactory(Object target) {
            this.target = target;
        }
        
         public Object getProxyInstance(){
             //1.工具類 Enhancer來(lái)指定要代理的目標(biāo)對(duì)象、實(shí)際處理代理邏輯的對(duì)象
             Enhancer en = new Enhancer();
             //2.設(shè)置父類
             en.setSuperclass(target.getClass());
             //3.設(shè)置回調(diào)函數(shù)
             en.setCallback(this);
             //4.創(chuàng)建子類(代理對(duì)象)
             return en.create();
         }
        
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("before.... ");//代理額外邏輯
            Object returnValue = method.invoke(target, args);
            System.out.println("after.... ");//代理額外邏輯
            return returnValue;
        }

    }
    
    public static void main(String[] args) throws Exception {
        UserService target = new UserServiceImpl();
        UserService proxy = (UserService) new ProxyFactory(target).getProxyInstance();
        proxy.login("Stephen", "123");
    }

}
2.3.1 使用spring-core實(shí)現(xiàn)cglib代理(優(yōu)化版本)

主要優(yōu)化點(diǎn):

提取抽象公共的ProxyFactory類

具體代理類的實(shí)現(xiàn)繼承自ProxyFactory

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class DynamicProxyBySpringCglibTest1 {

    //目標(biāo)接口
    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標(biāo)對(duì)象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //Common代理對(duì)象
    public static abstract class ProxyFactory implements MethodInterceptor {

        private Object target;
        
        public ProxyFactory(Object target) {
            this.target = target;
        }
        
        public Object getProxyInstance(){
             //1.工具類
             Enhancer en = new Enhancer();
             //2.設(shè)置父類
             en.setSuperclass(target.getClass());
             //3.設(shè)置回調(diào)函數(shù)
             en.setCallback(this);
             //4.創(chuàng)建子類(代理對(duì)象)
             return en.create();
         }
         
        protected abstract void before(Method method);
            
        protected abstract void after(Method method);
        
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            before(method);
            Object returnValue = method.invoke(target, args);
            after(method);
            return returnValue;
        }

    }
    
    //具體代理對(duì)象
    public static class UserServiceProxy extends ProxyFactory {

        public UserServiceProxy(Object target) {
            super(target);
        }

        @Override
        protected void before(Method method) {
            System.out.println("before.... " + method.getName());//代理額外邏輯
        }

        @Override
        protected void after(Method method) {
            System.out.println("after.... " + method.getName());//代理額外邏輯
        }
        
    }
    
    public static void main(String[] args) throws Exception {
        UserService target = new UserServiceImpl();
        UserService proxy = (UserService) new UserServiceProxy(target).getProxyInstance();
        proxy.login("Stephen", "123");
    }

}
3.Refs

API java.lang.reflect.Proxy

Spring Core ? 5.1.8.RELEASE

理解java的三種代理模式

java代理

Java代理和動(dòng)態(tài)代理機(jī)制分析和應(yīng)用

Java Proxy和CGLIB動(dòng)態(tài)代理原理

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75438.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.16 - 淺入淺出 JavaScript 函數(shù)式編程

    摘要:函數(shù)式編程,一看這個(gè)詞,簡(jiǎn)直就是學(xué)院派的典范。所以這期周刊,我們就重點(diǎn)引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對(duì)編程語(yǔ)言的理解更加融會(huì)貫通一些。但從根本上來(lái)說(shuō),函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...

    csRyan 評(píng)論0 收藏0
  • 信安 - 收藏集 - 掘金

    摘要:咱媽說(shuō)別亂點(diǎn)鏈接之淺談攻擊閱讀掘金作者馬達(dá)編輯迷鹿馬達(dá),精通開發(fā)開發(fā),擅長(zhǎng)接口設(shè)計(jì)以及平臺(tái)化建設(shè),獨(dú)自主導(dǎo)過(guò)多個(gè)產(chǎn)品。一題目購(gòu)物應(yīng)用分環(huán)境要求安全學(xué)習(xí)資料匯總掘金安全學(xué)習(xí)資料匯總安全學(xué)習(xí)網(wǎng)站收集 咱媽說(shuō)別亂點(diǎn)鏈接之淺談 CSRF 攻擊 - 閱讀 - 掘金作者 | 馬達(dá)編輯 | 迷鹿 馬達(dá), 精通PHP開發(fā)、Web開發(fā),擅長(zhǎng)api接口設(shè)計(jì)以及平臺(tái)化建設(shè),獨(dú)自主導(dǎo)過(guò)多個(gè)Web產(chǎn)品。目前就職...

    lushan 評(píng)論0 收藏0
  • 安全攻防戰(zhàn) - 收藏集 - 掘金

    摘要:咱媽說(shuō)別亂點(diǎn)鏈接之淺談攻擊閱讀掘金作者馬達(dá)編輯迷鹿馬達(dá),精通開發(fā)開發(fā),擅長(zhǎng)接口設(shè)計(jì)以及平臺(tái)化建設(shè),獨(dú)自主導(dǎo)過(guò)多個(gè)產(chǎn)品。一題目購(gòu)物應(yīng)用分環(huán)境要求安全學(xué)習(xí)資料匯總掘金安全學(xué)習(xí)資料匯總安全學(xué)習(xí)網(wǎng)站收集 咱媽說(shuō)別亂點(diǎn)鏈接之淺談 CSRF 攻擊 - 閱讀 - 掘金作者 | 馬達(dá)編輯 | 迷鹿 馬達(dá), 精通PHP開發(fā)、Web開發(fā),擅長(zhǎng)api接口設(shè)計(jì)以及平臺(tái)化建設(shè),獨(dú)自主導(dǎo)過(guò)多個(gè)Web產(chǎn)品。目前就職...

    chanthuang 評(píng)論0 收藏0
  • 淺入淺出FlowDroid(一): 簡(jiǎn)介&基本使用

    摘要:后文將圍繞做一些介紹。盡管如此,的使用對(duì)新手而言仍然充滿了困難。本系列文章基本為個(gè)人見解,難免有錯(cuò)誤與誤解,如有客觀錯(cuò)誤歡迎提出。 前言 說(shuō)到Android的污點(diǎn)分析框架,網(wǎng)上的搜索結(jié)果大多指向靜態(tài)的FlowDroid與動(dòng)態(tài)的TaintDroid。盡管由于加固、混淆等技術(shù)使得針對(duì)Android的靜態(tài)分析越來(lái)越困難,但靜態(tài)分析的無(wú)先驗(yàn)分析能力無(wú)法被動(dòng)態(tài)分析取代,使得靜態(tài)分析仍有發(fā)揮空間。...

    wqj97 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

lewif

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<