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

資訊專欄INFORMATION COLUMN

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

lewif / 3220人閱讀

摘要:代理模式的實現(xiàn)靜態(tài)代理優(yōu)缺點優(yōu)點只對對需要的方法加代理邏輯。通過繼承的方式進行代理,無論目標對象有沒有實現(xiàn)接口都可以代理,但是無法處理的情況。

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

1. Java代理的理解

代理模式是一種設(shè)計模式,簡單說即是在不改變源碼的情況下,實現(xiàn)對目標對象的功能擴展。
使用場景:如在方法執(zhí)行前后計算執(zhí)行時間,記錄日志等。在不改變原碼的條件下實現(xiàn)這些功能的擴展。

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

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

缺點: 1.每次代理都需要實現(xiàn)一個代理類;2. 代理類功能固定,無法靈活改變。3. 項目會有一大批代理的代碼,如果目標對象改變,代理類也需要對應(yīng)改變,不利于代碼的維護。

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

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

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

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

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

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對象
    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)用原實現(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");
    }

}

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

2.2 動態(tài)代理(JDK代理)

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

2.2.0 優(yōu)缺點

優(yōu)點: 動態(tài)代理所有接口。

缺點: 必須依賴使用接口方式來實現(xiàn)代理。

主要實現(xiàn)是使用JDK自帶的Proxy類來實現(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.

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

2.2.1 基本實現(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);
    }
    
    //目標對象
    public static class UserServiceImpl implements UserService {

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

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

                        @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;
        }
        
    }
    
    //獲取動態(tài)代理對象的公共方法
    @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();
        //代理對象1
        UserServiceImplProxy proxy = new UserServiceImplProxy(target);
        proxy.getProxy().login("Stephen", "123");
        
        //代理對象
        UserService jdkProxy = getJDKProxy(target);
        jdkProxy.login("JDK Stephen", "123");
    }

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

JDK Proxy動態(tài)代理進一步優(yōu)化:

抽象出代理父類

代理類實現(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 {
    //目標接口
    public interface UserService {
        public void login(String username, String pwd);
    }
    
    //目標對象
    public static class UserServiceImpl implements UserService {

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //代理對象
    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();
        //代理對象
        UserServiceImplProxy proxy = new UserServiceImplProxy(target);
        proxy.userServiceProxy.login("Stephen", "123");
    }

}
2.3 Cglib代理

CGLIB(Code Generation Library)是一個基于ASM的字節(jié)碼生成庫,它允許我們在運行時對字節(jié)碼進行修改和動態(tài)生成。
CGLIB通過繼承的方式進行代理,無論目標對象有沒有實現(xiàn)接口都可以代理,但是無法處理final的情況。

2.3.0 優(yōu)缺點

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

缺點:

在Spring的AOP編程中:

如果加入容器的目標對象有實現(xiàn)接口,用JDK代理

如果目標對象沒有實現(xiàn)接口,用Cglib代理

2.3.1 使用spring-core實現(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 {

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

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

        private Object target;
        
        public ProxyFactory(Object target) {
            this.target = target;
        }
        
         public Object getProxyInstance(){
             //1.工具類 Enhancer來指定要代理的目標對象、實際處理代理邏輯的對象
             Enhancer en = new Enhancer();
             //2.設(shè)置父類
             en.setSuperclass(target.getClass());
             //3.設(shè)置回調(diào)函數(shù)
             en.setCallback(this);
             //4.創(chuàng)建子類(代理對象)
             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實現(xiàn)cglib代理(優(yōu)化版本)

主要優(yōu)化點:

提取抽象公共的ProxyFactory類

具體代理類的實現(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 {

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

        @Override
        public void login(String username, String pwd) {
            System.out.println("Welcome " + username);
        }
        
    }
    
    //Common代理對象
    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)建子類(代理對象)
             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;
        }

    }
    
    //具體代理對象
    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代理和動態(tài)代理機制分析和應(yīng)用

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

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

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

相關(guān)文章

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

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

    csRyan 評論0 收藏0
  • 信安 - 收藏集 - 掘金

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

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

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

    chanthuang 評論0 收藏0
  • 淺入淺出FlowDroid(一): 簡介&基本使用

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

    wqj97 評論0 收藏0

發(fā)表評論

0條評論

lewif

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<