ݺߣ

ݺߣShare a Scribd company logo
Deutsche Bank
Аспектно-ориентированноеАспектно-ориентированное
программирование впрограммирование в
распределенных системах для javaраспределенных системах для java
разработчиков и QAразработчиков и QA
9.09.2015
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Аспектно-ориентированное программирование
Какие задачи решает АОП
Тестирование и модификация существующего приложения
• Доступность исходных кодов
• Перепаковка
• Модификация сторонних библиотек
• Итеративность изменений
Распределенное приложение
• Распространение изменений: classpath, конфигурация
• Оркестрация сервисов
Содержание
9/18/15 2010 DB Blue template
2
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Существующие решения
• BTrace
• Byteman
• AspectJ
• Пример: JDBC
AspectJ + MVEL + Maven = AspectJ-scripting
• AspectJ
• Pointcut syntax
• Concrete Aspects
• Bytecode modification
• LTW jvm agent / compile-time weaving
• MVEL
• Maven репозитарий, зависимости
• AspectJ-scripting
Содержание
9/17/15 2010 DB Blue template
3
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Примеры
● hawt.io
● метрики
● ssh server - CRaSH
● Логирование в Elasticsearch
● Hazelcast/CountDownLatch
Ограничения текущей реализации
Roadmap
• Groovy + Grape
• Модификация загрузчиков классов
• Конфигурация в maven/scm/fs/web
Заключение
Ресурсы
Q&A
Содержание
9/17/15 2010 DB Blue template
4
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Аспектно-ориентированное программирование (АОП) дополняет
объектно-ориентированное программирование (ООП),
предоставляя другой способ мышления о структуре
программы. Клюевой единицей модуляризации в ООП
является класс, в то время как в АОП единицей
модуляризации является аспект. Аспекты позволяют
эффективно выполнять модуляризацию сквозной
функциональности (crosscutting), такой как управление
транзакциями, логирование, проверка прав доступа, которые
затрагивают несколько объектов и типов.
Аспектно ориентированное
программирование
9/18/15 2010 DB Blue template
5
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
• Аспект (англ. aspect) — модуль или класс, реализующий сквозную функциональность. Аспект
изменяет поведение остального кода, применяя совет в точках соединения,
определенных некоторым срезом.
• Совет (advice) — средство оформления кода, которое должно быть вызвано из точки
соединения. Совет может быть выполнен до, после или вместо точки соединения. Типы
совета(advice): AROUND, BEFORE, AFTER, AFTER_RETURNING, AFTER_THROWING
• Точка соединения (join point) — точка в выполняемой программе, где следует применить
совет. Многие реализации АОП позволяют использовать вызовы методов и обращения к
полям объекта в качестве точек соединения.
• Срез (pointcut) — набор точек соединения. Срез определяет, подходит ли данная точка
соединения к данному совету. Самые удобные реализации АОП используют для
определения срезов синтаксис основного языка (например, в AspectJ применяются Java-
сигнатуры) и позволяют их повторное использование с помощью переименования и
комбинирования.
• Внедрение (Introduction/inter-type declaration) — изменение структуры класса и/или изменение
иерархии наследования для добавления функциональности аспекта в инородный код.
—
Аспектно-ориентированное
программирование
9/18/15 2010 DB Blue template
6
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {// do something }
// these settings have precedence for this method
@Transactional(readOnly = false, propagation =
Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) { // do something }
}
Какие задачи решает АОП
9/18/15 2010 DB Blue template
7
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Какие задачи решает АОП
9/18/15 2010 DB Blue template
8
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Модификация сторонних библиотек
Итеративность изменений
Тестирование и модификация существующего
приложения
9/18/15 2010 DB Blue template
9
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Доступность исходных кодов
Перепаковка
Тестирование и модификация существующего
приложения
9/18/15 2010 DB Blue template
10
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Распространение изменений: classpath, конфигурация
Оркестрация сервисов
Распределенное приложение
9/18/15 2010 DB Blue template
11
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
BTrace
btrace <pid> <btrace-script>
Существующие решения
9/18/15 2010 DB Blue template
12
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Byteman
-javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:appmain.btm
RULE trace main entry
CLASS AppMain
METHOD main
AT ENTRY
IF true
DO traceln("entering main")
ENDRULE
RULE trace main exit
CLASS AppMain
METHOD main
AT EXIT
IF true
DO traceln("exiting main")
ENDRULE
Существующие решения
9/18/15 2010 DB Blue template
13
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ
-javaagent:pathto/aspectjweaver.jar
aop.xml
@Aspect public class ProceedAspect {
@Pointcut("call(* setAge(..)) && args(i)")
void setAge(int i) {}
@Around("setAge(i)")
public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) {
return thisJoinPoint.proceed(new Object[]{i*2}); //using Java 5
autoboxing
}
}
Существующие решения
9/18/15 2010 DB Blue template
14
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Пример: JDBC
@Around(“execution(* oracle.net.ns.NetInputStream.read*(..)) “)
public Object emulateDbTimeout(ProceedingJoinPoint joinPoint){
...
Thread.sleep( jdbcTimeout + SAFE_PERCENT*jdbcTimeout );
…
}
@Around(“execution(* oracle.jdbc.driver.OracleStatement.cancel*(..)) “)
{
…
cancelled.set(true);
...
}
Существующие решения
9/18/15 2010 DB Blue template
15
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ: Pointcut syntax
https://eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html
execution(* org.sonar.server.app.WebServer.start(..))
call(* org.sonar.server.app.WebServer.start(..))
initialization(ConstructorPattern) execution(* *.new(..))
staticinitialization(ConstructorPattern)
get(FieldPattern)
set(FieldPattern)
—
AspectJ + MVEL + Maven = AspectJ-scripting
9/17/15 2010 DB Blue template
16
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ: Concrete Aspects
package mypack;
@Aspect public abstract class AbstractAspect {
// abstract pointcut: no expression is defined
@Pointcut abstract void scope();
@Before("scope() && execution(* *..doSome(..))")
public void before(JoinPoint jp) {
....
}
}
<aspectj>
<aspects>
<concrete-aspect name="mypack.__My__AbstractAspect"
extends="mypack.AbstractAspect">
<pointcut name="scope" expression="within(yourpackage..*)"/>
</concrete-aspect>
<aspects>
</aspectj>
AspectJ + MVEL + Maven = AspectJ-scripting
9/18/15 2010 DB Blue template
17
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ: Bytecode modification
AspectJ: LTW jvm agent / compile-time weaving
—
AspectJ + MVEL + Maven = AspectJ-scripting
9/17/15 2010 DB Blue template
18
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
MVEL
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.google.gson.GsonBuilder;
import com.thoughtworks.xstream.Xstream;
res = joinPoint.proceed();
gson = new GsonBuilder().setPrettyPrinting().create();
FileUtils.writeStringToFile(new File("report.json"), gson.toJson(res));
xstream = new XStream(); xstream.alias("issue",
org.apache.maven.plugin.issues.Issue);
FileUtils.writeStringToFile(new File("report.xml"), xstream.toXML(res));
res;
—
AspectJ + MVEL + Maven = AspectJ-scripting
9/17/15 2010 DB Blue template
19
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Maven репозитарий, зависимости
—
AspectJ + MVEL + Maven = AspectJ-scripting
9/18/15 2010 DB Blue template
20
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ-scripting
-javaagent:aspectj-scripting-1.0-agent.jar
-Dorg.aspectj.weaver.loadtime.configuration=config:file:database_console.xml
AspectJ + MVEL + Maven = AspectJ-scripting
9/18/15 2010 DB Blue template
21
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
—
Примеры: hawt.io
9/17/15 2010 DB Blue template
22
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Примеры: hawt.io
9/17/15 2010 DB Blue template
23
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<aspects>
<name>com.github.aspectjscripting.DumpMetrics</name>
<type>AFTER</type>
<pointcut>execution(public static void
com.github.aspectjscripting.Example.main(..))</pointcut>
<artifacts>
<artifact>com.github.igor-suhorukov:jvm-metrics:1.1</artifact>
<classRefs>
<variable>JmxCollect</variable><className>org.github.suhorukov.JmxCollect</classNa
me>
</classRefs>
<classRefs>
<variable>SigarCollect</variable><className>org.github.suhorukov.SigarCollect</class
Name>
</classRefs>
<classRefs>
<variable>PerformanceCounters</variable><className>org.github.suhorukov.Performan
ceCounters</className>
</classRefs>
</artifacts>
Примеры: метрики
9/17/15 2010 DB Blue template
24
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
<process>
<expression>
jmxCollect = new JmxCollect();
System.out.println(jmxCollect.getJsonJmxInfo("java.lang:type=Memory", new
java.util.Date()));
System.out.println(new SigarCollect().getJsonFullInfo());
performanceCounters = new PerformanceCounters();
System.out.println(performanceCounters.getJsonBaseInfo("sun.*"));
</expression>
</process>
</aspects>
</configuration>
Примеры: метрики
9/17/15 2010 DB Blue template
25
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
—
Примеры: CRaSH
9/17/15 2010 DB Blue template
26
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<aspects>
<name>com.github.igorsuhorukov.СrashubSsh</name>
<type>AFTER</type>
<pointcut>execution(* org.sonar.server.app.WebServer.start(..))</pointcut>
<artifacts>
<artifact>org.crashub:crash.connectors.ssh:1.3.1</artifact>
<classRefs><variable>Bootstrap</variable><className>org.crsh.standalone.Bootstra
p</className></classRefs>
<classRefs><variable>Builder</variable><className>org.crsh.vfs.FS$Builder</classN
ame></classRefs>
<classRefs><variable>ClassPathMountFactory</variable><className>org.crsh.vfs.spi.
url.ClassPathMountFactory</className></classRefs>
<classRefs><variable>FileMountFactory</variable><className>org.crsh.vfs.spi.file.Fil
eMountFactory</className></classRefs>
</artifacts>
<process>
<expression>
Примеры: ssh server - CRaSH
9/17/15 2010 DB Blue template
27
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
classLoader = Bootstrap.getClassLoader();
classpathDriver = new ClassPathMountFactory(classLoader);
otherCmd = new FileMountFactory(new java.io.File(System.getProperty("user.dir")));
cmdFS = new Builder().register("classpath", classpathDriver).register("file",
otherCmd).mount("classpath:/crash/commands/").mount("file:cmd/").build();
confFS = new Builder().register("classpath",
classpathDriver).mount("classpath:/crash/").build();
bootstrap = new Bootstrap(classLoader, confFS, cmdFS);
config = new java.util.Properties();
config.put("crash.ssh.port", "2000");
config.put("crash.ssh.auth_timeout", "300000");
config.put("crash.ssh.idle_timeout", "300000");
config.put("crash.auth", "simple");
config.put("crash.auth.simple.username", "admin");
config.put("crash.auth.simple.password", "admin");
bootstrap.setConfig(config);
bootstrap.bootstrap();
</expression>
</process>
</aspects>
</configuration>
—
Примеры: CRaSH
9/17/15 2010 DB Blue template
28
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Примеры: Логирование в Elasticsearch
9/17/15 2010 DB Blue template
29
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<aspects>
<name>com.github.igorsuhorukov.Loging</name>
<type>AROUND</type>
<pointcut>call(* org.slf4j.Logger.error(..)) || call(* org.slf4j.Logger.warn(..))
|| call(* org.slf4j.Logger.info(..)) || call(* org.slf4j.Logger.debug(..)) || call(*
org.slf4j.Logger.trace(..))</pointcut>
<process>
<expression>
res = joinPoint.proceed();
log = new java.util.HashMap();
log.put("level", joinPoint.getSignature().getName());
log.put("srcf", joinPoint.getSourceLocation().getFileName().substring(0,
joinPoint.getSourceLocation().getFileName().length()-5));
log.put("srcl", joinPoint.getSourceLocation().getLine());
Примеры: Логирование в Elasticsearch
9/18/15 2010 DB Blue template
30
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
if(joinPoint.getArgs()!=null &amp;&amp; joinPoint.getArgs().?length>0){
log.put("message", joinPoint.getArgs()[0].?toString());
if(joinPoint.getArgs().length > 1){
params = new java.util.HashMap();
for(i=1;i &lt; joinPoint.getArgs().length;i++){
if(joinPoint.getArgs()[i]!=null){
if(joinPoint.getArgs()[i].class.getName().equals("[Ljava.lang.Object;")){
for(j=0;j &lt; joinPoint.getArgs()[i].length;j++){
if( (joinPoint.getArgs()[i])[j] !=null){
params.put(i+"."+j,(joinPoint.getArgs()[i])[j].toString());
}
}
} else {
params.put(i,joinPoint.getArgs()[i].toString());
}
}
}
log.put("params", params);
}
}
log.put("host", reportHost); log.put("pid", pid);
log.put("@version", 1);
localDate = new java.util.Date();
Примеры: Логирование в Elasticsearch
9/18/15 2010 DB Blue template
31
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
lock.lock();
log.put("@timestamp", dateFormat.format(localDate));
index = "logstash-" + logstashFormat.format(localDate);
lock.unlock();
logSource = gson.toJson(log);
client.index(client.prepareIndex(index, "logs").setSource(logSource).request());
res;
</expression></process>
</aspects>
<globalContext>
<artifacts>
<artifact>com.google.code.gson:gson:2.3.1</artifact>
<classRefs>
<variable>GsonBuilder</variable>
<className>com.google.gson.GsonBuilder</className>
</classRefs>
</artifacts>
<artifacts>
<artifact>org.elasticsearch:elasticsearch:1.1.1</artifact>
<classRefs>
<variable>NodeBuilder</variable>
<className>org.elasticsearch.node.NodeBuilder</className>
</classRefs>
</artifacts>
Примеры: Логирование в Elasticsearch
9/17/15 2010 DB Blue template
32
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
<init>
<expression>
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.concurrent.locks.ReentrantLock;
reportHost = java.net.InetAddress.getLocalHost().getHostName();
pid =
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
gson = new GsonBuilder().create();
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
logstashFormat = new SimpleDateFormat("yyyy.MM.dd");
logstashFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
lock = new ReentrantLock();
client =
NodeBuilder.nodeBuilder().clusterName("distributed_app").data(false).client(true).node().client();
</expression>
</init>
</globalContext>
</configuration>
Примеры: Логирование в Elasticsearch
9/18/15 2010 DB Blue template
33
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
com.hazelcast:hazelcast:3.5.2
com.hazelcast.config.Config, com.hazelcast.core.Hazelcast,
com.hazelcast.core.HazelcastInstance, com.hazelcast.core.ICountDownLatch;
hazelcastInstance = Hazelcast.newHazelcastInstance(new Config());
countDownLatch = hazelcastInstance.getCountDownLatch("distributed-
countdown");
countDownLatch.trySetCount(5);
countDownLatch.countDown();
await = countDownLatch.await(100, java.util.concurrent.TimeUnit.SECONDS);
if(!await){
System.exit(-1);
}
// ...
result = joinPoint.proceed();
// ...
// ...
hazelcastInstance.shutdown();
result;
Примеры: Hazelcast/CountDownLatch
9/17/15 2010 DB Blue template
34
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Ограничения текущей реализации
9/17/15 2010 DB Blue template
35
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
— Groovy + Grape
Roadmap
9/17/15 2010 DB Blue template
36
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
— Модификация загрузчиков классов
— Конфигурация в maven/scm/fs/web
Roadmap
9/17/15 2010 DB Blue template
37
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Заключение
9/17/15 2010 DB Blue template
38
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
— https://kenai.com/projects/btrace/pages/Home
— http://byteman.jboss.org/
— https://eclipse.org/aspectj/doc/released/progguide/semantics-pointcut
s.html
— https://en.wikisource.org/wiki/MVEL_Language_Guide
— http://www.ibm.com/developerworks/java/tutorials/j-mavenv2/
— https://maven.apache.org/guides/introduction/introduction-to-reposito
ries.html
— https://maven.apache.org/guides/introduction/introduction-to-depe
ndency-mechanism.html
Ресурсы
9/17/15 2010 DB Blue template
39
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
— http://hawt.io
— http://www.crashub.org
— http://hazelcast.org
— https://www.elastic.co/products/elasticsearch
— http://habrahabr.ru/post/265741/
— http://habrahabr.ru/post/264415/
— http://habrahabr.ru/post/254571/
— http://habrahabr.ru/post/266781/
— http://habrahabr.ru/post/267009/
— http://docs.groovy-lang.org/latest/html/documentation/grape.html
Ресурсы
9/17/15 2010 DB Blue template
40
Игорь Сухоруков
Аспектно-ориентированное программирование 9.09.2015
Deutsche Bank
9/17/15 2010 DB Blue template
41
Deutsche Bank
Спасибо!
Игорь Сухоруков
igor.suhorukov@gmail.com
Спасибо!
Игорь Сухоруков
igor.suhorukov@gmail.com

More Related Content

Аспектно-ориентированное программирование в распределенных системах для java разработчиков и QA