Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
# Mobile Tools for Java (J2ME)
.mtj.tmp/

# vim swap files
*.swp

# Package Files #
*.jar
!gradle-wrapper.jar
Expand Down
Binary file removed .gradle/6.3/executionHistory/executionHistory.lock
Binary file not shown.
Binary file removed .gradle/6.3/fileChanges/last-build.bin
Binary file not shown.
Binary file removed .gradle/6.3/fileHashes/fileHashes.lock
Binary file not shown.
Empty file removed .gradle/6.3/gc.properties
Empty file.
Binary file removed .gradle/6.5/executionHistory/executionHistory.bin
Binary file not shown.
Binary file removed .gradle/6.5/executionHistory/executionHistory.lock
Binary file not shown.
Binary file removed .gradle/6.5/fileChanges/last-build.bin
Binary file not shown.
Binary file removed .gradle/6.5/fileHashes/fileHashes.bin
Binary file not shown.
Binary file removed .gradle/6.5/fileHashes/fileHashes.lock
Binary file not shown.
Empty file removed .gradle/6.5/gc.properties
Empty file.
Binary file removed .gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
2 changes: 0 additions & 2 deletions .gradle/buildOutputCleanup/cache.properties

This file was deleted.

Binary file removed .gradle/checksums/checksums.lock
Binary file not shown.
Empty file removed .gradle/vcs-1/gc.properties
Empty file.
3 changes: 0 additions & 3 deletions .idea/.gitignore

This file was deleted.

10 changes: 0 additions & 10 deletions .idea/compiler.xml

This file was deleted.

18 changes: 0 additions & 18 deletions .idea/gradle.xml

This file was deleted.

20 changes: 0 additions & 20 deletions .idea/jarRepositories.xml

This file was deleted.

7 changes: 0 additions & 7 deletions .idea/misc.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
# Примеры для курса "Разработчик Java" в OTUS

Разработайте такой функционал: метод класса можно пометить самодельной аннотацией @Log, например, так:

Группа 2020-09
class TestLogging { @Log public void calculation(int param) {}; }

### Преподаватели
Сергей Петрелевич<br>
Стрекалов Павел<br>
Александр Оруджев<br>
Вячеслав Лапин<br>
Виталий Куценко<br>
Дмитрий Коган
При вызове этого метода "автомагически" в консоль должны логироваться значения параметров. Например так.

Студент:
Kashapov Renat (Кашапов Ренат)<br>
renat.kashapov@gmail.com
class Demo { public void action() { new TestLogging().calculation(6); } }

В консоле дожно быть: executed method: calculation, param: 6

Обратите внимание: явного вызова логирования быть не должно.

Учтите, что аннотацию можно поставить, например, на такие методы: public void calculation(int param1) public void calculation(int param1, int param2) public void calculation(int param1, int param2, String param3)
26 changes: 26 additions & 0 deletions hw05-AOPprincipes/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
plugins {
id 'java'
id 'application'
}

group 'ru.otus'
version '1.0-SNAPSHOT'

repositories {
mavenCentral()
}

dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
// implementation 'com.google.guava:guava'
// https://mvnrepository.com/artifact/com.google.guava/guava
compile group: 'com.google.guava', name: 'guava', version: '30.0-jre'
// https://mvnrepository.com/artifact/cglib/cglib
compile group: 'cglib', name: 'cglib', version: '3.3.0'
// https://mvnrepository.com/artifact/org.ow2.asm/asm
compile group: 'org.ow2.asm', name: 'asm', version: '9.0'
// https://mvnrepository.com/artifact/org.ow2.asm/asm-util
compile group: 'org.ow2.asm', name: 'asm-util', version: '9.0'
}

mainClassName = 'aop.App'
43 changes: 43 additions & 0 deletions hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package aop;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import java.io.IOException;
import java.util.*;

import static org.objectweb.asm.Opcodes.ASM9;

public class AOPClassLoader extends ClassLoader {
protected Map<String, SomeMethodAttributes> loggedMethods = new HashMap<>();

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> resultClass = null;
if (!name.startsWith("java.")) {
try {
ClassReader cr = new ClassReader(name);
ClassWriter cw = new ClassWriter(0);
ClassWriter cw1 = new ClassWriter(0);
byte[] b2;
AOPLoggedMethodsNamesClassVisitor aopLoggedMethodsNamesClassVisitor = new AOPLoggedMethodsNamesClassVisitor(ASM9, cw, loggedMethods);
cr.accept(aopLoggedMethodsNamesClassVisitor, 0);
b2 = cw.toByteArray();
ClassReader c2 = new ClassReader(b2);
AOPLoggedMethodsCodeClassVisitor aopLoggedMethodsCodeClassVisitor = new AOPLoggedMethodsCodeClassVisitor(ASM9, cw1, loggedMethods);
c2.accept(aopLoggedMethodsCodeClassVisitor, 0);
b2 = cw1.toByteArray();
resultClass = defineClass(name, b2, 0, b2.length);
} catch (IOException e) {
e.printStackTrace();
}
} else {
resultClass = super.loadClass(name, resolve);
}
return resultClass;
}

@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package aop;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import java.util.Map;
import static org.objectweb.asm.Opcodes.ASM9;

public class AOPLoggedMethodsCodeClassVisitor extends ClassVisitor {

protected Map<String, SomeMethodAttributes> loggedMethods;

public AOPLoggedMethodsCodeClassVisitor(int asmVersion, ClassVisitor classVisitor, Map<String, SomeMethodAttributes> loggedMethods) {
super(asmVersion, classVisitor);
this.loggedMethods = loggedMethods;
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor superMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
if (loggedMethods.get(name + descriptor) != null) {
return new AOPLoggedMethodsCodeMethodVisitor(ASM9, superMethodVisitor, loggedMethods.get(name + descriptor));
}
return superMethodVisitor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package aop;

import org.objectweb.asm.MethodVisitor;
import static org.objectweb.asm.Opcodes.*;
import java.util.Map;

public class AOPLoggedMethodsCodeMethodVisitor extends MethodVisitor {

protected SomeMethodAttributes someMethodAttributes;

public AOPLoggedMethodsCodeMethodVisitor(int api, MethodVisitor methodVisitor, SomeMethodAttributes someMethodAttributes) {
super(api, methodVisitor);
this.someMethodAttributes = someMethodAttributes;
}

@Override
public void visitCode() {
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Method: \"" + someMethodAttributes.getName() + "\"");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
for (Map.Entry<String, AOPLoggedMethodsNamesMethodVisitor.TypeIndex> parameter : someMethodAttributes.getMethodVariablesHashMap().entrySet()) {
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Argument \"" + parameter.getKey() + "\": ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitVarInsn(parameter.getValue().getType().getOpcode(ILOAD), parameter.getValue().getIndex());
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(" + transformToPrintlnArg(parameter.getValue().getType().getDescriptor()) + ")V", false);
}
}

private String transformToPrintlnArg(String arg){
if(arg.matches("[BSI]{1}")){
return "I";
}
return arg;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package aop;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;

import java.util.Map;
import static org.objectweb.asm.Opcodes.*;

public class AOPLoggedMethodsNamesClassVisitor extends ClassVisitor {

protected Map<String, SomeMethodAttributes> loggedMethods;

public AOPLoggedMethodsNamesClassVisitor(int asmVersion, ClassVisitor classVisitor, Map<String, SomeMethodAttributes> loggedMethods) {
super(asmVersion, classVisitor);
this.loggedMethods = loggedMethods;
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor aopLoggedMethodsNamesMethodVisitor = new AOPLoggedMethodsNamesMethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions), loggedMethods, new SomeMethodAttributes(descriptor, access, name, signature, exceptions, new MethodVariablesHashMap()));
return aopLoggedMethodsNamesMethodVisitor;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package aop;

import org.objectweb.asm.*;
import java.util.Map;

public class AOPLoggedMethodsNamesMethodVisitor extends MethodVisitor {
protected boolean isLogPresent;
protected SomeMethodAttributes someMethodAttributes;
protected Map<String, SomeMethodAttributes> loggedMethods;

public AOPLoggedMethodsNamesMethodVisitor(int api, MethodVisitor methodVisitor, Map<String, SomeMethodAttributes> loggedMethods, SomeMethodAttributes someMethodAttributes) {
super(api, methodVisitor);
this.loggedMethods = loggedMethods;
this.someMethodAttributes = someMethodAttributes;
}

@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
isLogPresent = Type.getDescriptor(Log.class).equals(descriptor);
if(isLogPresent){
loggedMethods.put(someMethodAttributes.getName() + someMethodAttributes.getDescription(), someMethodAttributes);
}
return super.visitAnnotation(descriptor, visible);
}

@Override
public void visitMaxs(int maxStack, int maxLocals) {
mv.visitMaxs(maxStack + 3, maxLocals + 4);
}

@Override
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
String methodParameters = someMethodAttributes.getDescription().replaceFirst(".*\\(","").replaceFirst("\\).*", "");
if (isLogPresent & index > 0) {
someMethodAttributes.getMethodVariablesHashMap().put(name,new TypeIndex(index, parseParameters(methodParameters, index)));
}
super.visitLocalVariable(name, descriptor, signature, start, end, index);
}

private Type parseParameters(String parameters, int index) {
if (index == 1) {
if (parameters.startsWith("L")) {
return Type.getType(parameters.substring(0,parameters.indexOf(';')+1));
} else {
return Type.getType(parameters.substring(0, 1));
}
} else {
if (parameters.startsWith("L")){
return parseParameters(parameters.substring(parameters.indexOf(';')+1),index-1);
} else {
return parseParameters(parameters.substring(1),index-1);
}
}
}

final protected class TypeIndex {
private int index;
private Type type;

TypeIndex(int index, Type type) {
this.index = index;
this.type = type;
}

protected int getIndex() {
return index;
}

protected Type getType() {
return type;
}
}
}
27 changes: 27 additions & 0 deletions hw05-AOPprincipes/src/main/java/aop/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package aop;

import java.lang.reflect.Method;

public class App {
static public void main(String ... args) {
var classLoaderClass = App.class.getClassLoader().getClass();
if( !classLoaderClass.getName().equals(AOPClassLoader.class.getName())) { //иначе сравнивать классы невозможно, так как это различные объекты
AOPClassLoader aopClassLoader = new AOPClassLoader();
try {
Class<?> loadClass = aopClassLoader.loadClass("aop.App", false);
Method method = loadClass.getMethod("main", new Class[]{String[].class});
method.invoke(null, new Object[]{args});
} catch (Exception e) {
e.printStackTrace();
}
} else{// классы с AOP писать в этом блоке.
try {
new UsefulImpl().sayHelloTo("bb");
new UsefulImpl().sayHelloTo("cc", (short) 23);
}
catch (Exception e){
e.printStackTrace();
}
}
}
}
8 changes: 8 additions & 0 deletions hw05-AOPprincipes/src/main/java/aop/Log.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package aop;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
Loading