diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/pom.xml b/2022-02/spring-04-aop/aop-demo/aop-custom/pom.xml new file mode 100644 index 00000000..32ea04a7 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + ru.otus + aop-custom + 1.0 + + + 11 + 11 + UTF-8 + 1.9.8 + + + + + org.aspectj + aspectjrt + ${aspectj.version} + + + org.aspectj + aspectjweaver + ${aspectj.version} + + + diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/Main.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/Main.java new file mode 100644 index 00000000..fc62438c --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/Main.java @@ -0,0 +1,47 @@ +package ru.otus.demo; + +import ru.otus.demo.aop.LoggingAspect; +import ru.otus.demo.dao.BookDao; +import ru.otus.demo.dao.BookDaoSimple; +import ru.otus.demo.dao.PersonDao; +import ru.otus.demo.dao.PersonDaoSimple; +import ru.otus.demo.service.BookService; +import ru.otus.demo.service.BookServiceImpl; +import ru.otus.demo.service.PersonService; +import ru.otus.demo.service.PersonServiceImpl; +import ru.otus.demo.aop.SimpleWeaver; + +import java.util.HashMap; +import java.util.Map; + +public class Main { + + public static void main(String[] args) { + + SimpleWeaver weaver = new SimpleWeaver(); + LoggingAspect aspect = new LoggingAspect(); + + // Как будто контекст с бинами (пока без аспекта) + Map, Object> context = new HashMap<>(); + context.put(PersonDao.class, new PersonDaoSimple()); + context.put(BookDao.class, new BookDaoSimple()); + + // Колхозный вивинг + context.forEach((key, value) -> context.put(key, weaver.weave(value, aspect))); + + // Как будто достаем из контекста дао (уже с примененным аспектом) + PersonDao personDaoProxy = (PersonDao) context.get(PersonDao.class); + BookDao bookDaoProxy = (BookDao) context.get(BookDao.class); + + // Внедряем в сервисы + PersonService personService = new PersonServiceImpl(personDaoProxy); + BookService bookService = new BookServiceImpl(bookDaoProxy); + + // Используем сервисы + personService.getByName("Вася"); + System.out.println("-------------------------------------------------"); + bookService.getByTitle("Укротители велосипедов"); + } + + +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/LoggingAspect.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/LoggingAspect.java new file mode 100644 index 00000000..e8537435 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/LoggingAspect.java @@ -0,0 +1,20 @@ +package ru.otus.demo.aop; + +import org.aspectj.lang.JoinPoint; + +import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Collectors; + +public class LoggingAspect { + + public void logBefore(JoinPoint joinPoint) { + System.out.println("Прокси : " + joinPoint.getThis().getClass().getName()); + System.out.println("Класс : " + joinPoint.getTarget().getClass().getName()); + + System.out.println("Вызов метода : " + joinPoint.getSignature().getName()); + System.out.println("Аргументы метода : " + Arrays.stream(joinPoint.getArgs()) + .map(Objects::toString) + .collect(Collectors.joining(", "))); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleAOPInvocationHandler.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleAOPInvocationHandler.java new file mode 100644 index 00000000..52489be2 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleAOPInvocationHandler.java @@ -0,0 +1,24 @@ +package ru.otus.demo.aop; + +import org.aspectj.lang.JoinPoint; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class SimpleAOPInvocationHandler implements InvocationHandler { + private final Object target; + private final LoggingAspect aspect; + + public SimpleAOPInvocationHandler(Object target, LoggingAspect aspect) { + this.target = target; + this.aspect = aspect; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + JoinPoint joinPoint = new SimpleJoinPoint(target, + proxy, args, method); + aspect.logBefore(joinPoint); + return method.invoke(target, args); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleJoinPoint.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleJoinPoint.java new file mode 100644 index 00000000..b80fd999 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleJoinPoint.java @@ -0,0 +1,67 @@ +package ru.otus.demo.aop; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.SourceLocation; + +import java.lang.reflect.Method; + +public class SimpleJoinPoint implements JoinPoint { + private final Object targetClass; + private final Object proxyClass; + private final Object[] args; + private final Signature targetMethodSignature; + + public SimpleJoinPoint(Object target, Object proxy, Object[] args, + Method targetMethod) { + this.targetClass = target; + this.proxyClass = proxy; + this.args = args; + this.targetMethodSignature = new SimpleSignature(targetMethod); + } + + @Override + public String toShortString() { + throw new UnsupportedOperationException(); + } + + @Override + public String toLongString() { + throw new UnsupportedOperationException(); + } + + @Override + public Object getThis() { + return proxyClass; + } + + @Override + public Object getTarget() { + return targetClass; + } + + @Override + public Object[] getArgs() { + return args; + } + + @Override + public Signature getSignature() { + return targetMethodSignature; + } + + @Override + public SourceLocation getSourceLocation() { + throw new UnsupportedOperationException(); + } + + @Override + public String getKind() { + throw new UnsupportedOperationException(); + } + + @Override + public StaticPart getStaticPart() { + throw new UnsupportedOperationException(); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleSignature.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleSignature.java new file mode 100644 index 00000000..1a525c24 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleSignature.java @@ -0,0 +1,43 @@ +package ru.otus.demo.aop; + +import org.aspectj.lang.Signature; + +import java.lang.reflect.Method; + +public class SimpleSignature implements Signature { + private final Method targetMethod; + + public SimpleSignature(Method targetMethod) { + this.targetMethod = targetMethod; + } + + @Override + public String toShortString() { + throw new UnsupportedOperationException(); + } + + @Override + public String toLongString() { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + return targetMethod.getName(); + } + + @Override + public int getModifiers() { + throw new UnsupportedOperationException(); + } + + @Override + public Class getDeclaringType() { + throw new UnsupportedOperationException(); + } + + @Override + public String getDeclaringTypeName() { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleWeaver.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleWeaver.java new file mode 100644 index 00000000..7e46c016 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/aop/SimpleWeaver.java @@ -0,0 +1,16 @@ +package ru.otus.demo.aop; + +import ru.otus.demo.Main; + +import java.lang.reflect.Proxy; + +public class SimpleWeaver { + @SuppressWarnings("unchecked") + public T weave(T classInstance, LoggingAspect aspect) { + return (T) Proxy.newProxyInstance( + Main.class.getClassLoader(), + classInstance.getClass().getInterfaces(), + new SimpleAOPInvocationHandler(classInstance, aspect) + ); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDao.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDao.java new file mode 100644 index 00000000..17a905ba --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDao.java @@ -0,0 +1,8 @@ +package ru.otus.demo.dao; + +import ru.otus.demo.domain.Book; + +public interface BookDao { + + Book findByTitle(String title); +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDaoSimple.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDaoSimple.java new file mode 100644 index 00000000..56a0b41d --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/BookDaoSimple.java @@ -0,0 +1,10 @@ +package ru.otus.demo.dao; + +import ru.otus.demo.domain.Book; + +public class BookDaoSimple implements BookDao { + @Override + public Book findByTitle(String title) { + return new Book(title); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDao.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDao.java new file mode 100644 index 00000000..15563d64 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDao.java @@ -0,0 +1,8 @@ +package ru.otus.demo.dao; + +import ru.otus.demo.domain.Person; + +public interface PersonDao { + + Person findByName(String name); +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDaoSimple.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDaoSimple.java new file mode 100644 index 00000000..7adbfddf --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/dao/PersonDaoSimple.java @@ -0,0 +1,11 @@ +package ru.otus.demo.dao; + +import ru.otus.demo.domain.Person; + + +public class PersonDaoSimple implements PersonDao { + + public Person findByName(String name) { + return new Person(name, 18); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Book.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Book.java new file mode 100644 index 00000000..d54a119f --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Book.java @@ -0,0 +1,14 @@ +package ru.otus.demo.domain; + +public class Book { + + private String title; + + public Book(String name) { + this.title = name; + } + + public String getTitle() { + return title; + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Person.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Person.java new file mode 100644 index 00000000..80ee7acf --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/domain/Person.java @@ -0,0 +1,20 @@ +package ru.otus.demo.domain; + +public class Person { + + private String name; + private int age; + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookService.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookService.java new file mode 100644 index 00000000..713e4e82 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookService.java @@ -0,0 +1,8 @@ +package ru.otus.demo.service; + +import ru.otus.demo.domain.Book; + +public interface BookService { + + Book getByTitle(String title); +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookServiceImpl.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookServiceImpl.java new file mode 100644 index 00000000..713dc0e5 --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/BookServiceImpl.java @@ -0,0 +1,17 @@ +package ru.otus.demo.service; + +import ru.otus.demo.dao.BookDao; +import ru.otus.demo.domain.Book; + +public class BookServiceImpl implements BookService { + private final BookDao bookDao; + + public BookServiceImpl(BookDao bookDao) { + this.bookDao = bookDao; + } + + @Override + public Book getByTitle(String title) { + return bookDao.findByTitle(title); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonService.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonService.java new file mode 100644 index 00000000..5a3ae9ab --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonService.java @@ -0,0 +1,8 @@ +package ru.otus.demo.service; + +import ru.otus.demo.domain.Person; + +public interface PersonService { + + Person getByName(String name); +} diff --git a/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonServiceImpl.java b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonServiceImpl.java new file mode 100644 index 00000000..29240b6e --- /dev/null +++ b/2022-02/spring-04-aop/aop-demo/aop-custom/src/main/java/ru/otus/demo/service/PersonServiceImpl.java @@ -0,0 +1,17 @@ +package ru.otus.demo.service; + +import ru.otus.demo.dao.PersonDao; +import ru.otus.demo.domain.Person; + +public class PersonServiceImpl implements PersonService { + + private final PersonDao dao; + + public PersonServiceImpl(PersonDao dao) { + this.dao = dao; + } + + public Person getByName(String name) { + return dao.findByName(name); + } +} diff --git a/2022-02/spring-04-aop/aop-demo/pom.xml b/2022-02/spring-04-aop/aop-demo/pom.xml index 2da9b147..950b1292 100644 --- a/2022-02/spring-04-aop/aop-demo/pom.xml +++ b/2022-02/spring-04-aop/aop-demo/pom.xml @@ -13,6 +13,7 @@ aop-ctw aop-ctw-plain + aop-custom aop-ltw aop-native