Полный анализ самовызова SpringAOP

Java
Полный анализ самовызова SpringAOP

Резюме

Семейная корзина Spring помогает веб-разработчикам Java сэкономить много времени на разработке и повысить эффективность. Однако, поскольку многие детали скрыты, многие разработчики только знают об этом и не знают, почему.Эта статья предназначена для анализа некоторых аннотаций с использованием Spring, которые не могут быть вызваны сами по себе. Так как таких статей много, некоторые места не будут подробно описаны, а другие статьи будут цитироваться напрямую.

проблема

  1. Какие аннотации в Spring нельзя использовать для самовызова
  2. Почему прокси не может позвонить сам?
  3. Обычно используется весной@Cache, @Async,@TransactionВ чем разница между этими тремя принципами?
  4. Как решить проблему самовызова
  5. Каковы подводные камни использования разных решений?

Обзор АОП

В первую очередь необходимо уточнить несколько существительных, которые необходимо различатьAOP Spring AOP AspectJ

AOP

Аспектно-ориентированное программирование, аспектно-ориентированное программирование, идея решения проблем, реализует некоторые повторяющиеся проблемы кодирования через аспекты. Многие понимают, что аспекты понимаются через Spring, поэтому возникает непонимание, что Spring AOP и AOP приравниваются, но это не так.

Spring AOP

Весенний АОПпростоПосадочная реализация АОП, в основном обеспечивает реализацию АОП в контейнере Spring, и без Spring работать не будет. Spring AOP не является полным решением AOP.

Многие компоненты Spring такие, как Spring-Session, Spring-jdbc, Spring-Cache и т. д., могут решить некоторые общие требования, но будет много ограничений, Если вы хотите использовать более глубокие и гибкие функции реализации, вам все равно нужно использовать другие профессиональные компоненты/фреймворки.

SpringAOP по умолчанию реализован в режиме прокси, то есть JDK Proxy/CGLib. Я не буду вдаваться в подробности о прокси, JDK Proxy и CGLib.

在这里插入图片描述

AspectJ

Spring AOP не является полным решением AOP, в отличие от AspectJ. AspectJ вплетает аспекты в целевые классы в компиляторе

решение

Реализация SpringAop представлена ​​выше, а решение выделено ниже.

Способ 1 — внедрить прокси-бин в себя

Для этого нет веской причины

    @Autowired
    @Lazy
    private AsyncMethod asyncMethod;
	  public void testAsync() {
        System.out.println(Thread.currentThread().getName());
		// 调用注入的bean
        asyncMethod.testAsnc3();
    }
    @Async
    public void testAsnc3() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("async3");
    }

Note

Будет проблема циклической зависимости, используйте@Lazyрешать

Способ 2 -AopContext.currentProxy()Получить текущий прокси-объект

использовать

Сначала нужно настроить@EnableAspectJAutoProxy(exposeProxy = true), позволяя получить прокси-класс в коде

 public void testAsync() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("async1");
      ((AsyncMethod)AopContext.currentProxy()).testAsnc2();
    }
	@Async
    public void testAsnc2() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("async2");
    }

Принципиальный анализ

Эта реализация может смотреть на класс AopContext,

// 通过ThreadLocal来实现的
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy");

Затем Spring Aop автоматически настраивает прокси, устанавливаяexposeProxyпроблема собственности. Кто-то написал это, так что я больше не буду писать

cloud.Tencent.com/developer/ ах…

Note

  1. Поскольку используется SpringAOP, будут ограничения на режим прокси.
  2. AopContext.currentProxy() использует ThreadLocal, поэтому он не может пересекать потоки.
  3. Ограничения на параметры bean-компонента, такие как методы создания прокси @Async, отличаются от других | методов

Способ 3 — использовать AspectJ напрямую

Поскольку проблема самовызова вызвана тем, что Spring AOP реализуется в режиме прокси, не будет ли она решена без использования режима прокси?

использовать

  1. переключиться в режим прокси
@EnableAsync(mode = AdviceMode.ASPECTJ)
  1. Добавьте зависимости пакета для ткачества аспекта.
 <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-instrument -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-instrument</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>

  1. использовать
 public void testAsync() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("async1");
        testAsnc2();
    }

    /**
     * 测试ASPECTJ调用
     */
    @Async
    private void testAsnc2() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("async2");
    }

  1. Метод запуска AspectJ — компилятор вплетает аспект в целевой класс, а при запуске нужно добавить параметры java-агента
-Dserver.port=1000 -javaagent:${classpath}\spring-instrument-4.2.5.RELEASE.jar  
-javaagent:${classpath}\aspectjweaver-1.8.8.jar

Суммировать

метод ограничение
вызывающий сам себя Ограничения режима прокси, такие как только публичные, нестатические методы
AopContext.currentProxy() 1. Ограничение режима прокси 2. Ограничение ThreadLocal, не может пересекать потоки 3. Ограничение настроек бина, например метод создания прокси @Async отличается от других
AspectJ Неограниченный, немного хлопотно использовать

Обратите внимание на паблик-аккаунт [Abbot's Temple], как можно скорее получите обновление статьи и начните путь технической практики вместе с настоятелем

在这里插入图片描述

Ссылаться на

блог. Помогите мне. Тогда /2017/08/31/…

cloud.Tencent.com/developer/ ах…

F правильно A вы ошибаетесь.com/software-of…

docs.spring.IO/spring-без оперативной памяти…

Woohoo. Принесите арлингтон-терьера.com/spring-op-…