Upload
igor-suhorukov
View
563
Download
3
Embed Size (px)
Citation preview
Deutsche Bank
Аспектно-ориентированное Аспектно-ориентированное программирование в программирование в распределенных системах для java распределенных системах для java разработчиков и QAразработчиков и QA9.09.2015
Игорь СухоруковАспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Аспектно-ориентированное программированиеКакие задачи решает АОПТестирование и модификация существующего приложения• Доступность исходных кодов• Перепаковка• Модификация сторонних библиотек• Итеративность измененийРаспределенное приложение• Распространение изменений: classpath, конфигурация• Оркестрация сервисов
Содержание
9/18/15 2010 DB Blue template
2
Игорь СухоруковАспектно-ориентированное программирование 9.09.2015
Deutsche Bank
Существующие решения• BTrace• Byteman• AspectJ• Пример: JDBCAspectJ + 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
BTracebtrace <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 entryCLASS AppMainMETHOD mainAT ENTRYIF trueDO traceln("entering main")ENDRULE
RULE trace main exitCLASS AppMainMETHOD mainAT EXITIF trueDO traceln("exiting main")ENDRULE
Существующие решения
9/18/15 2010 DB Blue template
13
Игорь СухоруковАспектно-ориентированное программирование 9.09.2015
Deutsche Bank
AspectJ-javaagent:pathto/aspectjweaver.jaraop.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</className>
</classRefs> <classRefs>
<variable>SigarCollect</variable><className>org.github.suhorukov.SigarCollect</className>
</classRefs> <classRefs>
<variable>PerformanceCounters</variable><className>org.github.suhorukov.PerformanceCounters</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.Bootstrap</className></classRefs>
<classRefs><variable>Builder</variable><className>org.crsh.vfs.FS$Builder</className></classRefs>
<classRefs><variable>ClassPathMountFactory</variable><className>org.crsh.vfs.spi.url.ClassPathMountFactory</className></classRefs>
<classRefs><variable>FileMountFactory</variable><className>org.crsh.vfs.spi.file.FileMountFactory</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 && 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 < joinPoint.getArgs().length;i++){ if(joinPoint.getArgs()[i]!=null){ if(joinPoint.getArgs()[i].class.getName().equals("[Ljava.lang.Object;")){ for(j=0;j < 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-pointcuts.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-repositories.html
— https://maven.apache.org/guides/introduction/introduction-to-dependency-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