ホームページ  >  記事  >  Java  >  Java AOP動的プロキシとは何ですか?

Java AOP動的プロキシとは何ですか?

WBOY
WBOY転載
2023-04-24 19:43:051467ブラウズ
    #1.IOC と AOP の概念

    IOC: 制御の反転、オブジェクトの作成、オブジェクト間の呼び出しプロセス、春はそれを管理します。 IOC を使用する目的は、結合を減らすことです。

    AOP: アスペクト指向プログラミング。プリコンパイルと実行時の動的プロキシを通じてプログラム機能の統合保守を実現するテクノロジー。 AOP は、ソフトウェア開発のホットスポットである OOP の継続であり、Spring フレームワークの重要な内容であり、関数型プログラミングの派生パラダイムです。 AOP を使用すると、ビジネス ロジックのさまざまな部分を分離できるため、ビジネス ロジックのさまざまな部分間の結合が軽減され、プログラムの再利用性が向上し、開発の効率が向上します。 AOP の基盤となる実装はダイナミック プロキシに基づいています (実装方法は、インターフェイスに切り替える場合は JDK ネイティブのダイナミック プロキシを使用し、通常のメソッドに切り替える場合は cglib ダイナミック プロキシを使用します)。

    2. ダイナミックプロキシを使用する理由

    ビジネスの継続的拡大に伴い:

    (1) ログ機能: ログコードが変更されると多くの修正が必要になります。

    (2) 検証機能: 複数箇所を検証する必要がある場合は、複数の変更を行う必要があります。

    現時点では、問題を解決するには動的プロキシを使用する必要があります。動的プロキシを実装するには 2 つの方法があります:

    [1]JDK ネイティブ動的プロキシ: 欠点は、インターフェイスに基づいて完了する必要があります

    [2]cglib 動的プロキシ: インターフェイスベースがなくても完了できます

    #2.1 JDK ネイティブ動的プロキシ

    ##2.1.1 MathService インターフェース クラス

    public interface MathService {
        //+
        public Double add(double a,double b);
        //-
        public Double sub(double a,double b);
        //*
        public Double mul(double a,double b);
        ///
        public Double div(double a,double b);
    }
    Java AOP動的プロキシとは何ですか?2.1.2 MathServiceImpl 実装インターフェース クラス

    public class MathServiceImpl implements MathService{
        @Override
        public Double add(double a, double b) {
            Double result=a+b;
            return result;
        }
        @Override
        public Double sub(double a, double b) {
            Double result=a-b;
            return result;
        }
        @Override
        public Double mul(double a, double b) {
            Double result=a*b;
            return result;
        }
        @Override
        public Double div(double a, double b) {
            Double result=a/b;
            return result;
        }
    }
    2.1.3 ProxyFactory 動的プロキシ ファクトリ
    public class ProxyFactory {
        //被代理对象
        private Object target;
        public ProxyFactory(Object target) {
            this.target = target;
        }
        //获取代理对象
        public Object getProxy(){
            /**
             * ClassLoader loader, 被代理对象的类加载器
             * Class<?>[] interfaces, 被代理对象实现的接口
             * InvocationHandler h: 当代理对象执行被代理的方法时,会触发该对象中的invoke功能
             */
            ClassLoader loader=target.getClass().getClassLoader();
            Class<?>[] interfaces=target.getClass().getInterfaces();
            InvocationHandler h=new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //可以加上需要的非业务代码
                    //method.getName()获取方法名
                    // Arrays.asList(args)获取输入值
                    System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
                    //method:表示代理对象要代理的方法
                    //invoke:回调该函数
                    //args:方法需要的参数
                    Object result = method.invoke(target, args);//代理对象回调该方法
                    return result;
                }
            };
            //先写此处方法,才可找到上述三个方法填写方式
            Object o = Proxy.newProxyInstance(loader, interfaces, h);
            return o;
        }
    }
    2.1.4 テスト クラス
    public class Test01 {
        public static void main(String[] args) {
            MathServiceImpl target=new MathServiceImpl();
            ProxyFactory proxyFactory=new ProxyFactory(target);
            MathService proxy = (MathService) proxyFactory.getProxy();
            Double add = proxy.add(15.0, 5.0);
            System.out.println(add);
        }
    }
    2.2 cglib 動的プロキシ

    2.2.1 MathServiceImpl クラス

    public class MathServiceImpl{
        public Double add(double a, double b) {
            Double result=a+b;
            return result;
        }
        public Double sub(double a, double b) {
            Double result=a-b;
            return result;
        }
        public Double mul(double a, double b) {
            Double result=a*b;
            return result;
        }
        public Double div(double a, double b) {
            Double result=a/b;
            return result;
        }
    }
    Java AOP動的プロキシとは何ですか?2.2.2 ProxyFactory 動的プロキシ ファクトリ

    Note:
    (1) はじめに cglib の jar パッケージ。

    cglib

    3.2 .5




    (2) プロキシ クラス ファクトリを作成し、インターフェイス MethodInterceptor を実装します。
    public class ProxyFactory implements MethodInterceptor {
        private Object target;
        public ProxyFactory(Object target) {
            this.target = target;
        }
        //获取代理对象
        public Object getProxy(){
            Enhancer enhancer=new Enhancer();
            //指定被代理对象的父类
            enhancer.setSuperclass(target.getClass());
            //指定回调类
            enhancer.setCallback(this);
            //创建代理对象
            return enhancer.create();
        }
        //当代理对象执行代理方法时触发的方法
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    //        System.out.println("before++++++++++++++++++++");
    //        Object result = method.invoke(target, args);
            //可以加上需要的非业务代码
            //method.getName()获取方法名
            // Arrays.asList(args)获取输入值
            System.out.println("this is "+method.getName()+" method begin with"+ Arrays.asList(args));
            //method:表示代理对象要代理的方法
            //invoke:回调该函数
            //args:方法需要的参数
            Object result = method.invoke(target, args);//代理对象回调该方法
            return result;
        }
    }
    2.2.3 テストクラス
    public class Test01 {
        public static void main(String[] args) {
            MathServiceImpl target=new MathServiceImpl();
            ProxyFactory proxyFactory=new ProxyFactory(target);
            MathServiceImpl proxy = (MathServiceImpl) proxyFactory.getProxy();
            Double add = proxy.add(1, 2);
            System.out.println(add);
        }
    }

    3.AOP動的プロキシ

    3.1 対応する依存関係を追加

    <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>5.2.15.RELEASE</version>
        </dependency>
    Java AOP動的プロキシとは何ですか? 3.2 spring.xml ファイルの構成

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--包扫描-->
        <context:component-scan base-package="com.qy151wd.proxy.proxy.aop"/>
        <!--开启aop注解-->
        <aop:aspectj-autoproxy/>
    </beans>

    3.3 MathService インターフェイス クラス

    public interface MathService {
        public Double add(double a, double b);
        public Double sub(double a, double b);
        public Double mul(double a, double b);
        public Double div(double a, double b);
    }

    3.4 MathServiceImpl 実装インターフェイス クラス

    @Service
    public class MathServiceImpl implements MathService {
        @Override
        public Double add(double a, double b) {
            Double result=a+b;
            return result;
        }
        @Override
        public Double sub(double a, double b) {
            Double result=a-b;
            return result;
        }
        @Override
        public Double mul(double a, double b) {
            Double result=a*b;
            return result;
        }
        @Override
        public Double div(double a, double b) {
            Double result=a/b;
            return result;
        }
    }

    3.5 LogAspect クラス

    @Service //若是使用@component也可以
    @Aspect //表示该类为切面类
    public class LogAspect {
        //任意返回类型 aop包下的所有类都有切面日志 使用通配符
        //第一个*:修饰符和返回值类型
        //第二个*:所有类
        //第三个*:所有方法
        @Before("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")
        public void before(){
            System.out.println("方法执行前的日志");
        }
        @After("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))") //总会被执行,不管有没有异常
        public void after(){
            System.out.println("方法执行后的日志");
        }
        @AfterReturning("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//只有碰到return后才会执行
        public void afterReturning(){
            System.out.println("碰到return后执行");
        }
        @AfterThrowing("execution(* com.qy151wd.proxy.proxy.aop.*.*(..))")//异常通知
        public void afterThrowing(){
            System.out.println("出现异常了");
        }
    }

    3.6 テスト クラス

    りー

    以上がJava AOP動的プロキシとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。