text:
Mục lục
- 1- Giới thiệu
- 2- Các yêu cầu trước khi bắt đầu
- 3- Các lớp tham gia vào các ví dụ
- 4- Tạo AspectJ Project
- 5- Ví dụ đầu tiên bắt đầu với AspectJ
- 6- Các khái niệm cơ bản trong AspectJ
-
- 7- Ví dụ AspectJ cơ bản
-
- 7.1- Quy tắc mô tả class, method, * và ..
- 7.2- Target & args
- 7.3- Toán tử && ||
- 7.4- Field trong AspectJ
- 7.5- Khai báo kiểu nội bộ (Inter-type declarations)
- 7.6- Tracking
- 7.7- Cflow
- 7.8- Cflowbelow
Hướng dẫn lập trình Java hướng khía cạnh với AspectJ (AOP)
- 1- Giới thiệu
- 2- Các yêu cầu trước khi bắt đầu
- 3- Các lớp tham gia vào các ví dụ
- 4- Tạo AspectJ Project
- 5- Ví dụ đầu tiên bắt đầu với AspectJ
- 6- Các khái niệm cơ bản trong AspectJ
-
- 7- Ví dụ AspectJ cơ bản
-
- 7.1- Quy tắc mô tả class, method, * và ..
- 7.2- Target & args
- 7.3- Toán tử && ||
- 7.4- Field trong AspectJ
- 7.5- Khai báo kiểu nội bộ (Inter-type declarations)
- 7.6- Tracking
- 7.7- Cflow
- 7.8- Cflowbelow
-
TÀI LIỆU ĐANG ĐƯỢC VIẾT 50%.
-
1- Giới thiệu
-
Tài liệu này được viết dựa trên:
-
-
Eclipse 4.4 (LUNA)
-
AspectJ 1.8.2
-
-
2- Các yêu cầu trước khi bắt đầu
-
Bạn cần cài đặt công cụ phát triển AspectJ vào Eclipse, bạn có thể xem hướng dẫn tại:
-
-
3- Các lớp tham gia vào các ví dụ
-
Trong tài liệu này tôi sử dụng một số class, nó tham gia vào nhiều ví dụ minh họa AspectJ.
-
- Box
- FigureElement
- Group
- Line
- Point
- ShapeFigureElement
- SlotfulPoint
-
Nguồn các class này lấy tại:
-
-
-
Box.java
package figures; import java.awt.Rectangle; import java.awt.Shape; public class Box extends ShapeFigureElement { private Point _p0; private Point _p1; private Point _p2; private Point _p3; public Box(int x0, int y0, int width, int height) { _p0 = new Point(x0, y0); _p1 = new Point(x0 + width, y0); _p2 = new Point(x0 + width, y0 + height); _p3 = new Point(x0, y0 + height); } public Point getP0() { return _p0; } public Point getP1() { return _p1; } public Point getP2() { return _p2; } public Point getP3() { return _p3; } @Override public void move(int dx, int dy) { _p0.move(dx, dy); _p1.move(dx, dy); _p2.move(dx, dy); _p3.move(dx, dy); } public void checkBoxness() { if ((_p0.getX() == _p3.getX()) && (_p1.getX() == _p2.getX()) && (_p0.getY() == _p1.getY()) && (_p2.getY() == _p3.getY())) return; throw new IllegalStateException("This is not a square."); } @Override public String toString() { return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")"; } @Override public Shape getShape() { return new Rectangle(getP1().getX(), getP1().getY(), getP3().getX() - getP1().getX(), getP3().getY() - getP1().getY()); } }
-
FigureElement.java
package figures; import java.awt.*; import java.awt.geom.*; public interface FigureElement { public static final Rectangle MAX_BOUNDS = new Rectangle(0, 0, 500, 500); public abstract void move(int dx, int dy); public abstract Rectangle getBounds(); public abstract boolean contains(Point2D p); public abstract void paint(Graphics2D g2); }
-
Group.java
package figures; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Group implements FigureElement { private Collection _members; private String _identifier; public Group(FigureElement first) { this._members = new ArrayList(); add(first); } public void add(FigureElement fe) { _members.add(fe); } public Iterator members() { return _members.iterator(); } public void move(int dx, int dy) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); fe.move(dx, dy); } } public void setIdentifier(String identifier) { _identifier = identifier; } @Override public String toString() { if (_identifier != null) { return _identifier; } StringBuffer buf = new StringBuffer("Group("); for (Iterator i = _members.iterator(); i.hasNext();) { buf.append(i.next().toString()); if (i.hasNext()) { buf.append(", "); } } buf.append(")"); return buf.toString(); } public Rectangle getBounds() { Rectangle previous = null; for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); Rectangle rect = fe.getBounds(); if (previous != null) { previous = previous.union(rect); } else { previous = rect; } } return previous; } public boolean contains(Point2D p) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); if (fe.contains(p)) return true; } return false; } public void paint(Graphics2D g2) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); fe.paint(g2); } } public int size() { return _members.size(); } }
-
Line.java
package figures; import java.awt.*; import java.awt.geom.*; public class Line extends ShapeFigureElement { private Point _p1; private Point _p2; public Line(Point p1, Point p2) { _p1 = p1; _p2 = p2; } public Point getP1() { return _p1; } public Point getP2() { return _p2; } @Override public void move(int dx, int dy) { _p1.move(dx, dy); _p2.move(dx, dy); } @Override public String toString() { return "Line(" + _p1 + ", " + _p2 + ")"; } /** * Used to determine if this line {@link contains(Point2D)} a point. */ final static int THRESHHOLD = 5; /** * Returns true if the point segment distance is less than * {@link THRESHHOLD}. */ @Override public boolean contains(Point2D p) { return getLine2D().ptLineDist(p) < THRESHHOLD; } private Line2D getLine2D() { return new Line2D.Float((float) getP1().getX(), (float) getP1().getY(), (float) getP2().getX(), (float) getP2().getY()); } public Shape getShape() { return getLine2D(); } }
-
Point.java
package figures; import java.awt.*; import java.awt.geom.*; public class Point extends ShapeFigureElement { private int _x; private int _y; public Point(int x, int y) { _x = x; _y = y; } public int getX() { return _x; } public int getY() { return _y; } public void setX(int x) { _x = x; } public void setY(int y) { _y = y; } @Override public void move(int dx, int dy) { _x += dx; _y += dy; } @Override public String toString() { return "Point(" + _x + ", " + _y + ")"; } /** The height of displayed {@link Point}s. */ private final static int HEIGHT = 10; /** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */ private final static int WIDTH = Point.HEIGHT; @Override public Shape getShape() { return new Ellipse2D.Float((float) getX() - Point.WIDTH / 2, (float) getY() - Point.HEIGHT / 2, (float) Point.HEIGHT, (float) Point.WIDTH); } }
-
ShapeFigureElement.java
package figures; import java.awt.*; import java.awt.geom.*; public abstract class ShapeFigureElement implements FigureElement { @Override public abstract void move(int dx, int dy); public abstract Shape getShape(); @Override public Rectangle getBounds() { return getShape().getBounds(); } @Override public boolean contains(Point2D p) { return getShape().contains(p); } public Color getLineColor() { return Color.black; } public Color getFillColor() { return Color.red; } @Override public final void paint(Graphics2D g2) { Shape shape = getShape(); g2.setPaint(getFillColor()); g2.fill(shape); g2.setPaint(getLineColor()); g2.draw(shape); } }
-
SlothfulPoint.java
package figures; import java.awt.*; import java.awt.geom.*; /** * This class makes mistakes to be caught by invariant checkers. */ public class SlothfulPoint extends ShapeFigureElement { private int _x; private int _y; public SlothfulPoint(int x, int y) { } public int getX() { return _x; } public int getY() { return _y; } public void setX(int x) { } public void setY(int y) { } @Override public void move(int dx, int dy) { System.out.println("Slothful moving"); } @Override public String toString() { return "SlothfulPoint"; } @Override public Shape getShape() { return new Ellipse2D.Float((float) _x, (float) _y, 1.0f, 1.0f); } }
-
4- Tạo AspectJ Project
-
Trước hết tạo một Project thông thường, lấy tên là AspectJTutorial.
-
-
Nhấn phải chuột vào Project, chọn Configure/Convert to AspectJ Project.
-
-
Convert thành công:
-
-
5- Ví dụ đầu tiên bắt đầu với AspectJ
-
Trước hết chúng ta làm một ví dụ đầu tiên, trước khi bắt đầu với các khái niệm:
-
Tạo class HelloAspectJDemo:
-
HelloAspectJDemo.java
package org.o7planning.tutorial.aspectj.helloaspectj; public class HelloAspectJDemo { public static void sayHello() { System.out.println("Hello"); } public static void greeting() { String name = new String("John"); sayHello(); System.out.print(name); } public static void main(String[] args) { sayHello(); System.out.println("--------"); sayHello(); System.out.println("--------"); greeting(); } }
-
Một class như trên là hoàn toàn không có gì đáng chú ý, tuy nhiên đặt ra vấn đề bạn muốn chương trình làm một cái gì đó ngay trước, hoặc ngay sau khi phương thức sayHello() được gọi, chẳng hạn in ra màn hình câu thông báo. Theo cách truyền thống bạn sẽ thêm vào một dòng lệnh in ra màn hình ngay trước khi gọi sayHello().
-
-
AspectJ là một hướng lập trình khía cạnh (aspect programming), nó cho bạn một giải pháp khác để giải quyết vấn đề này, tất nhiên AspectJ còn làm được nhiều hơn thế. Hãy nhớ đây chỉ là ví dụ HelloWorld.
-
- File/New/Other..
-
-
-
Một file có tên: HelloAspectJ.aj đã được tạo ra, nó có cấu trúc khá giống với một class.
-
AspectJ các phiên bản trước kia sử dụng Annotation để mô tả, các phiên bản gần đây mới đưa vào file *.aj. Trong tài liệu này tôi bỏ qua không sử dụng Annotation, vì nó không rõ ràng bằng việc sử dụng file *.aj. Ngoài ra file *.aj có ngữ pháp giống một class, eclipse sẽ thông báo giúp bạn ngữ pháp viết sai.
-
-
Sửa code của HelloAspectJ.aj:
-
HelloAspectJ.aj
package org.o7planning.tutorial.aspectj.helloaspectj; public aspect HelloAspectJ { // Định nghĩa ra một pointcut. // call: gọi method sayHello() của class HelloAspectJDemo pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); before() : callSayHello() { System.out.println("Before call sayHello"); } after() : callSayHello() { System.out.println("After call sayHello"); } }
-
AspectJ có chút khác biệt với một class thông thường nó thêm vào rất nhiều các từ khóa. Và file có đuôi là *.aj chứ không phải là *.java. Một số từ khóa của AspectJ:
-
- aspect pointcut privileged call execution
- initialization preinitialization handler get set
- staticinitialization target args within withincode
- cflow cflowbelow annotation before after around
- proceed throwing returning adviceexecution declare
- parents warning error soft precedence thisJoinPoint
- thisJoinPointStaticPart thisEnclosingJoinPointStaticPart
- issingleton perthis pertarget percflow percflowbelow
- pertypewithin lock unlock thisAspectInstance
-
-
Quay trở lại với ví dụ HelloWorld. Bây giờ chúng ta chạy class HelloAspectJDemo. Và kết quả nhận được:
-
-
AspectJ là vô cùng mạnh mẽ. Chẳng hạn với ví dụ trên nếu bạn sửa lại code trên HelloAspectJ.aj một chút có thể làm cho nó có tác dụng trên mọi class gọi hàm sayHello().
-
// Định nghĩa ra một pointcut. // call: gọi method sayHello() của class HelloAspectJDemo pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); // Sửa lại thành: // Có nghĩa là mọi nơi (class, aspectj) gọi sayHello() pointcut callSayHello(): call(* *.sayHello());
-
6- Các khái niệm cơ bản trong AspectJ
-
Trong AspectJ bạn cần phân biệt một số khái niệm:
-
- Advice
- Pointcut
- JoinPoint
-
-
6.1- JoinPoint
-
JoinPoint (Điểm tham gia) là một điểm được xác định rõ ràng trong dòng chảy của chương trình
-
- Chúng ta muốn thi hành một đoạn code (“advice”) mỗi lần gặp điểm JoinPont.
- Chúng ta không muốn làm lộn xộn code bằng việc chỉ rõ ràng “Đây là các điểm tham gia”
- Nghĩa là không tự viết code vào các vị trí đó.
- AspectJ cung cấp một cú pháp để chỉ ra những JoinPoint "từ bên ngoài" mã thực tế.
- Đánh dấu chúng lại rồi thực thi code nào đó viết bên ngoài.
-
JoinPoint là một điểm trong dòng chảy chương trình "Nơi một cái gì đó sẽ xảy ra", cái gì ở đây có thể là:
-
- Nơi method được gọi
- Nơi một ngoại lệ đã ném ra
- Nơi biến được truy cập (accessed)
- Nơi khởi tạo một đối tượng
- Nơi tham chiếu tới một đối tượng.
-
Như vậy JoinPoint rất đa dạng, vị trí bạn khởi tạo một đối tượng thì đó cũng coi là một JoinPoint.
-
Quay lại với ví dụ HelloWorld chúng ta sẽ xác định một số JoinPoint:
-
-
6.2- PointCut
-
Định nghĩa Pointcut bao gồm một bên trái và một bên phải, cách nhau bằng dấu hai chấm
-
- Phía bên trái bao gồm các tên pointcut và các tham số pointcut (chẳng hạn, các dữ liệu có sẵn khi các sự kiện xảy ra)
- Bên phải chứa bản thân Pointcut
-
Ví dụ:
-
pointcut callSayHello(): call(* HelloAspectJDemo.sayHello());
-
- Tên của Pointcut là callSayHello
- Pointcut này không có tham số
- Bản thân Pointcut là call(* HelloAspectJDemo.sayHello())
- Pointcut này đề cập đến bất kỳ thời điểm nào phương thức HelloAspectJDemo.sayHello() được gọi.
-
-
6.3- Advice
-
Quay trở lại với ví dụ HelloWorld, chúng ta có 2 advice
-
- before()
- after()
-
-
Advice (Tư vấn hoặc lời khuyên) xác định một hành vi. Các đoạn code của một Advice sẽ được chạy ở mọi điểm tham gia (Join point) của Pointcut. Chính xác cách thức mã này được chạy phụ thuộc vào loại Advice (loại tư vấn).
-
AspectJ hỗ trợ ba loại Advice. Các loại Advice xác định nó tương tác như thế nào với các JoinPoint (điểm tham gia) nó được định nghĩa. Vì vậy AspectJ chia ra before (chạy trước) JoinPoint, after (chạy sau) JoinPoint, và around (chạy tại chỗ hoặc "xung quanh") JoinPoint.
-
Trong khi "before Advice" là tương đối không có vấn đề, với "after Advice" có 3 tình huống: Sau khi thực hiện của một JoinPoint hoàn thành bình thường, sau khi ném một ngoại lệ, hoặc sau khi thực hiện một trong hai. AspectJ cho phép "after Advice" cho bất kỳ hai tình huống này.
-
- TODO: Giải thích thêm "around Advice".
-
Để dễ hiểu chúng ta xem một vài ví dụ với Advice:
-
HelloAspectJ2.aj
package org.o7planning.tutorial.aspectj.helloaspectj; public aspect HelloAspectJ2 { pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); // Advice loại "after returning". after() returning (Object retObj): callSayHello() { System.out.println("Returned normally with " + retObj); } // Advice loại "after throwing". after() throwing (Exception e): callSayHello() { System.out.println("Threw an exception: " + e); } // Bao gồm cả 2 tình huống trả về bình thường // Hoặc bị ngoại lệ khi gọi method (sayHello) after() : callSayHello() { System.out.println("Returned or threw an Exception"); } }
-
Loại Advice "after returning" có thể không cần quan tâm tới giá trị trả về (của method) lúc đó có có thể viết.
-
// Advice loại "after returning". // Quan tâm tới giá trị trả về after() returning (Object retObj): callSayHello() { System.out.println("Returned normally with " + retObj); } // Advice loại "after returning" không cần quan tâm tới Object trả về. after() returning(): callSayHello() { System.out.println("Returned normally"); } // Hoặc // Advice loại "after returning" không cần quan tâm tới Object trả về. after() returning : callSayHello() { System.out.println("Returned normally"); }
-
-
7- Ví dụ AspectJ cơ bản
-
Trước khi đi vào chi tiết nâng cao, chúng ta xem các ví dụ cơ bản, và các quy tắc trong AspectJ, nếu không hiểu được các quy tắc này bạn không thể hiểu được AspectJ.
-
-
7.1- Quy tắc mô tả class, method, * và ..
-
Trong AspectJ nếu bạn muốn nhắc tới một lớp, một phương thức trong khai báo Pointcut bạn cần phải ghi tên đầy đủ của nó. Ví dụ:
-
- figures.Point
- figures.Point.setX(int)
-
Trường hợp class và AspectJ cùng trong một package thì bạn có thể ghi một cách ngắn gọn. Ví dụ:
-
- Point
- Point.setX(int)
-
Hãy xem một ví dụ minh họa dưới đây, AspectJ01.aj và class Point nằm trong 2 package khác nhau.
-
-
AspectJ01.aj
package org.o7planning.tutorial.aspectj.demo01; public aspect AspectJ01 { // Class Point và AspectJ này không cùng package // vì vậy phải ghi rõ cả package (Bắt buộc). // Pointcut này định nghĩa các điểm tham gia (JoinPoint) // chỉ trong phạm vi class ClassTest01 // ClassTest01 và AspectJ này cùng package, // vì vậy có thể bỏ qua package trong within. pointcut callSetX() : call(void figures.Point.setX(int)) && within (ClassTest01) ; // Advice before() : callSetX() { System.out.println("Before call Point.setX(int)"); } }
-
ClassTest01.java
package org.o7planning.tutorial.aspectj.demo01; import figures.Point; public class ClassTest01 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.setX(20); System.out.println("---- (2) ----"); point.setY(100); System.out.println("---- (3) ----"); } }
-
Kết quả chạy lớp ClassTest01:
-
-
Như vậy tại đây có một số ghi chú:
-
// within sử dụng để hạn chế phạm vi của Pointcut // trong trường hợp dưới đây // Chỉ chứa các điểm tham gia (JoinPoint) trong class ClassTest01. within (ClassTest01) // Có thể sử dụng import import figures.Point; ..... // Và có thể viết ngắn gọn. pointcut callSetX() : call(void Point.setX(int)) && within (ClassTest01) ;
-
Dấu * trong AspectJ
-
// Tập hợp các JoinPont gọi method Point.setX(int) với package bất kỳ. pointcut callSetX() : call(void *.Point.setX(int)) ; // Tập hợp các Pointcut gọi Point.setX(int) với package bất kỳ // và kiểu trả về bất kỳ. pointcut callSetX() : call(* *.Point.setX(int)) ; // Pointcut gọi các method tĩnh setX(int) của một class có tên *Point (APoint, AbcPoint,...) // và thuộc package sample, kiểu trả về int. pointcut callSetX() : call(public static int sample.*Point.setX(int)) ; // Sử dụng (..) để mô tả method có 0 hoặc nhiều tham số. pointcut callSetX() : call(public static int sample.*Point.setX(..)) ;
-
7.2- Target & args
-
target: Là đối tượng tham gia tại JoinPoint (Điểm tham gia), đối tượng gọi method(hoặc đối tượng truy cập field).
args: Là tham số.
Hãy xem ví dụ minh họa:
-
AspectJ02.aj
package org.o7planning.tutorial.aspectj.demo02; // Đã import class Point. import figures.Point; public aspect AspectJ02 { // Pointcut, khi gọi Point.move(int,int) // Sử dụng target để khai báo đối tượng tham gia // Sử dụng args để khai báo các tham số. // within để hạn chế các JoinPoint chỉ trong class ClassTest02. pointcut callMove(Point point, int dx, int dy) : call(* figures.Point.move(int,int)) && args(dx,dy) && target(point) && within(ClassTest02) ; before(Point point, int dx, int dy) : callMove(point, dx, dy ) { System.out.println("Before call move(" + dx + "," + dy + ")"); System.out.println(point.toString()); } }
-
ClassTest02.java
package org.o7planning.tutorial.aspectj.demo02; import figures.Point; public class ClassTest02 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.move(20, 30); System.out.println("---- (2) ----"); System.out.println(point.toString()); System.out.println("---- (3) ----"); point.setX(100); } }
-
-
Kết quả chạy ví dụ
-
-
7.3- Toán tử && ||
-
AspectJ03.aj
package org.o7planning.tutorial.aspectj.demo03; // Chú ý: Phải import FigureElement & Point import figures.FigureElement; import figures.Point; public aspect AspectJ03 { // Pointcut gồm các hành động di chuyển (move) pointcut moveAction() : ( call(void FigureElement.move(int,int)) || call(void Point.setX(int)) || call(void Point.setY(int)) ) && within (ClassTest03); before() : moveAction() { System.out.println("before move"); } }
-
ClassTest03.java
package org.o7planning.tutorial.aspectj.demo03; import figures.FigureElement; import figures.Line; import figures.Point; public class ClassTest03 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.setX(20 ); System.out.println("---- (2) ----"); FigureElement line= new Line(new Point(1,1), new Point(10,10)); line.move(10, 10); System.out.println("---- (3) ----"); } }
-
Kết quả chạy ví dụ
-
-
7.4- Field trong AspectJ
-
FieldInAspectJ.aj
package org.o7planning.tutorial.aspectj.demo04; import java.io.PrintStream; public aspect FieldInAspectJ { // Field in AspectJ. PrintStream logStream = System.err; pointcut move() : call(* figures.Point.move(int,int)) && within(FieldInAspectJTest); before(): move() { logStream.println("Before Point move"); } }
-
FieldInAspectJTest.java
package org.o7planning.tutorial.aspectj.demo04; import figures.Point; public class FieldInAspectJTest { public static void main(String[] args) { Point point = new Point(10, 200); System.err.println("---- (1) ----"); point.setX(20); System.err.println("---- (2) ----"); point.move(10, 10); System.err.println("---- (3) ----"); } }
-
Kết quả chạy ví dụ:
-
-
7.5- Khai báo kiểu nội bộ (Inter-type declarations)
-
PointObserving.aj
package org.o7planning.tutorial.aspectj.demo05; import java.util.ArrayList; import java.util.List; import figures.Point; public aspect PointObserving { // Class Point hoàn toàn không có field: observers // Tuy nhiên vẫn có thể khai báo tại đây. // observers: Ghi lại các vị trí điểm thay đổi. private List<Point> Point.observers = new ArrayList<Point>(); pointcut moveAction(Point point) : call(void Point.move(int,int) ) && target(point) && within(PointObservingTest); after(Point point) : moveAction(point) { System.out.println("Point moved"); // Thêm vào vị trí mới. point.observers.add(point); // Ghi ra các vị trí của điểm đã đi qua. System.out.println(" - "+point.observers); } public static void addObserver(Point p) { // p.observers.add(s); } public static void removeObserver(Point p) { // p.observers.remove(s); } }
-
PointObservingTest.java
package org.o7planning.tutorial.aspectj.demo05; import figures.Point; public class PointObservingTest { public static void main(String[] args) { Point point1 = new Point(100, 100); // Di chuyển lần 1 point1.move(10, 10); // Di chuyển lần 2 point1.move(10, 10); System.out.println("----------------------"); Point point2 = new Point(200, 200); // Di chuyển lần 1 point2.move(15, 10); // Di chuyển lần 2 point2.move(15, 10); // Di chuyển lần 3 point2.move(25, 10); } }
-
Kết quả chạy ví dụ:
-
-
7.6- Tracking
-
Tracking: Nghĩa là theo dấu vết (Các phương thức nào đã được gọi và lần lượt thế nào, hoặc diễn biến của cái gì đó ...)
-
Chúng ta sẽ tạo một Aspect, nó định nghĩa một pointcut chứa các điểm tham gia là các nơi mà phương thức thực thi, và cũng tạo một Advice để định nghĩa đoạn code sẽ được thực thi tại các vị trí đó.
-
SimpleTracing.aj
package org.o7planning.tutorial.aspectj.demo06; import org.aspectj.lang.Signature; public aspect SimpleTracing { // Tập hợp các JoinPoint tại vị trí gọi method bất kỳ. // và nằm trong class SimpleTracingTest. pointcut tracedCall() : call (* *(..)) // && !within(SimpleTracing) && within(SimpleTracingTest) ; before() : tracedCall() { Signature sig = thisJoinPointStaticPart.getSignature(); String line = "" + thisJoinPointStaticPart.getSourceLocation().getLine(); String sourceName = thisJoinPointStaticPart.getSourceLocation() .getWithinType().getCanonicalName(); // System.out.println("Call from " + sourceName + " line " + line + "\n to " + sig.getDeclaringTypeName() + "." + sig.getName() +"\n"); } }
-
SimpleTracingTest.java
package org.o7planning.tutorial.aspectj.demo06; import figures.Point; public class SimpleTracingTest { private static void testMethod1() { Point point = new Point(100, 100); point.setX(100); } private static void testMethod2() { String text = "This is text"; String s = text.substring(2); System.out.println(s); } public static void main(String[] args) { testMethod1(); testMethod2(); } }
-
Kết quả chạy ví dụ:
-
-
Ví dụ trên tôi giới hạn việc ghi ra thông tin các method được gọi bên trong code của class SimpleTrackingTest. Nếu bạn bỏ điều kiện để loại bỏ các JoinPoint trên chính aspect SimpleTracking, điều này là cần thiết để tránh một vòng lặp vô tận.
-
7.7- Cflow
-
Luồng điều khiển (control flow) là luồng các điểm thực hiện của chương trình bên trong của một điểm tham gia (JointPoint) cụ thể. cflow() và cflowbelow() được tạo ra để tóm lấy các điểm tham gia khác như là một thông số và cho phép chúng ta định nghĩa một luồng điều khiển dựa trên pointcut - pointcuts này sẽ tóm tất cả các điểm tham gia trong luồng điều khiển của từng Joinpoint cụ thể.
-
cflow() sẽ tóm lấy tất cả các điểm tham gia (join point) như call, execution, set và get field, error handlers trong luồng điều khiển của một JointPont cụ thể.
-
Hình minh họa dưới đây chứa các JointPoint gọi phương thức MyClass.callA().
-
-
Sử dụng cflow(..):
-
-
-
Xem ví dụ chi tiết:
-
-
CflowAspectJ.aj
package org.o7planning.tutorial.aspectj.demo07; public aspect CflowAspectJ { pointcut call_cflow_callA() : cflow( call( * MyClass.callA() ) ) && within(CFlowDemo || MyClass); before() : call_cflow_callA() { System.out.println( "Join Point at: " + thisJoinPointStaticPart.getSourceLocation().getWithinType().getCanonicalName() + " --> " + thisJoinPointStaticPart.getSourceLocation().getLine()); } }
-
MyClass.java
package org.o7planning.tutorial.aspectj.demo07; public class MyClass { public void callA() { callB(); callC(); } public void callB() { callC(); } public void callC() { } }
-
CFlowDemo.java
package org.o7planning.tutorial.aspectj.demo07; public class CFlowDemo { public static void main(String[] args) { MyClass myClass= new MyClass(); myClass.callA(); myClass.callA(); } }
-
Kết quả chạy class CFlowDemo:
-
-
7.8- Cflowbelow
-
Luồng điều khiển (control flow) là luồng các điểm thực hiện của chương trình bên trong của một điểm tham gia (JointPoint) cụ thể. cflow() và cflowbelow() được tạo ra để tóm lấy các điểm tham gia khác như là một thông số và cho phép chúng ta định nghĩa một luồng điều khiển dựa trên pointcut - pointcuts này sẽ tóm tất cả các điểm tham gia trong luồng điều khiển của từng Joinpoint cụ thể.
-
cflowbelow() có hành vi giống với cflow, nhưng nó không tóm điểm tham gia trong tham số của nó, và tóm tất cả các điểm tham gia còn lại.
-
Bạn có thể xem thêm ở mục cflow().
-
-

markdown:
### Mục lục
[]
-
1-
[Giới thiệu](#a27086)
-
2-
[Các yêu cầu trước khi bắt đầu](#a27090)
-
3-
[Các lớp tham gia vào các ví dụ](#a27201)
-
4-
[Tạo AspectJ Project](#a27235)
-
5-
[Ví dụ đầu tiên bắt đầu với AspectJ](#a27249)
-
6-
[Các khái niệm cơ bản trong AspectJ](#a27291)
-
-
7-
[Ví dụ AspectJ cơ bản](#a27431)
-
-
7.1-
[Quy tắc mô tả class, method, * và ..](#a27509)
-
7.2-
[Target & args](#a27567)
-
7.3-
[Toán tử && ||](#a27588)
-
7.4-
[Field trong AspectJ](#a27602)
-
7.5-
[Khai báo kiểu nội bộ (Inter-type declarations)](#a27616)
-
7.6-
[Tracking](#a27630)
-
7.7-
[Cflow](#a159498)
-
7.8-
[Cflowbelow](#a791980)
- 7.1-
# Hướng dẫn lập trình Java hướng khía cạnh với AspectJ (AOP)
[]
-
1-
[Giới thiệu](#a27086)
-
2-
[Các yêu cầu trước khi bắt đầu](#a27090)
-
3-
[Các lớp tham gia vào các ví dụ](#a27201)
-
4-
[Tạo AspectJ Project](#a27235)
-
5-
[Ví dụ đầu tiên bắt đầu với AspectJ](#a27249)
-
6-
[Các khái niệm cơ bản trong AspectJ](#a27291)
-
-
7-
[Ví dụ AspectJ cơ bản](#a27431)
-
-
7.1-
[Quy tắc mô tả class, method, * và ..](#a27509)
-
7.2-
[Target & args](#a27567)
-
7.3-
[Toán tử && ||](#a27588)
-
7.4-
[Field trong AspectJ](#a27602)
-
7.5-
[Khai báo kiểu nội bộ (Inter-type declarations)](#a27616)
-
7.6-
[Tracking](#a27630)
-
7.7-
[Cflow](#a159498)
-
7.8-
[Cflowbelow](#a791980)
- 7.1-
-
## TÀI LIỆU ĐANG ĐƯỢC VIẾT 50%.
-
[1- Giới thiệu]
-
Tài liệu này được viết dựa trên:
-
-
### Eclipse 4.4 (LUNA)
-
### AspectJ 1.8.2
-
-
[2- Các yêu cầu trước khi bắt đầu]
-
Bạn cần cài đặt công cụ phát triển
**AspectJ**vào **Eclipse**, bạn có thể xem hướng dẫn tại:
-
-
[3- Các lớp tham gia vào các ví dụ]
-
Trong tài liệu này tôi sử dụng một số class, nó tham gia vào nhiều ví dụ minh họa
**AspectJ**.
-
**Box** **FigureElement** **Group** **Line** **Point** **ShapeFigureElement** **SlotfulPoint**
-
-
Nguồn các class này lấy tại:
-
-
-
Box.java
package figures; import java.awt.Rectangle; import java.awt.Shape; public class Box extends ShapeFigureElement { private Point _p0; private Point _p1; private Point _p2; private Point _p3; public Box(int x0, int y0, int width, int height) { _p0 = new Point(x0, y0); _p1 = new Point(x0 + width, y0); _p2 = new Point(x0 + width, y0 + height); _p3 = new Point(x0, y0 + height); } public Point getP0() { return _p0; } public Point getP1() { return _p1; } public Point getP2() { return _p2; } public Point getP3() { return _p3; } @Override public void move(int dx, int dy) { _p0.move(dx, dy); _p1.move(dx, dy); _p2.move(dx, dy); _p3.move(dx, dy); } public void checkBoxness() { if ((_p0.getX() == _p3.getX()) && (_p1.getX() == _p2.getX()) && (_p0.getY() == _p1.getY()) && (_p2.getY() == _p3.getY())) return; throw new IllegalStateException("This is not a square."); } @Override public String toString() { return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")"; } @Override public Shape getShape() { return new Rectangle(getP1().getX(), getP1().getY(), getP3().getX() - getP1().getX(), getP3().getY() - getP1().getY()); } }
-
FigureElement.java
package figures; import java.awt.*; import java.awt.geom.*; public interface FigureElement { public static final Rectangle MAX_BOUNDS = new Rectangle(0, 0, 500, 500); public abstract void move(int dx, int dy); public abstract Rectangle getBounds(); public abstract boolean contains(Point2D p); public abstract void paint(Graphics2D g2); }
-
Group.java
package figures; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Group implements FigureElement { private Collection _members; private String _identifier; public Group(FigureElement first) { this._members = new ArrayList(); add(first); } public void add(FigureElement fe) { _members.add(fe); } public Iterator members() { return _members.iterator(); } public void move(int dx, int dy) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); fe.move(dx, dy); } } public void setIdentifier(String identifier) { _identifier = identifier; } @Override public String toString() { if (_identifier != null) { return _identifier; } StringBuffer buf = new StringBuffer("Group("); for (Iterator i = _members.iterator(); i.hasNext();) { buf.append(i.next().toString()); if (i.hasNext()) { buf.append(", "); } } buf.append(")"); return buf.toString(); } public Rectangle getBounds() { Rectangle previous = null; for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); Rectangle rect = fe.getBounds(); if (previous != null) { previous = previous.union(rect); } else { previous = rect; } } return previous; } public boolean contains(Point2D p) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); if (fe.contains(p)) return true; } return false; } public void paint(Graphics2D g2) { for (Iterator i = _members.iterator(); i.hasNext();) { FigureElement fe = (FigureElement) i.next(); fe.paint(g2); } } public int size() { return _members.size(); } }
-
Line.java
package figures; import java.awt.*; import java.awt.geom.*; public class Line extends ShapeFigureElement { private Point _p1; private Point _p2; public Line(Point p1, Point p2) { _p1 = p1; _p2 = p2; } public Point getP1() { return _p1; } public Point getP2() { return _p2; } @Override public void move(int dx, int dy) { _p1.move(dx, dy); _p2.move(dx, dy); } @Override public String toString() { return "Line(" + _p1 + ", " + _p2 + ")"; } /** * Used to determine if this line {@link contains(Point2D)} a point. */ final static int THRESHHOLD = 5; /** * Returns true if the point segment distance is less than * {@link THRESHHOLD}. */ @Override public boolean contains(Point2D p) { return getLine2D().ptLineDist(p) < THRESHHOLD; } private Line2D getLine2D() { return new Line2D.Float((float) getP1().getX(), (float) getP1().getY(), (float) getP2().getX(), (float) getP2().getY()); } public Shape getShape() { return getLine2D(); } }
-
Point.java
package figures; import java.awt.*; import java.awt.geom.*; public class Point extends ShapeFigureElement { private int _x; private int _y; public Point(int x, int y) { _x = x; _y = y; } public int getX() { return _x; } public int getY() { return _y; } public void setX(int x) { _x = x; } public void setY(int y) { _y = y; } @Override public void move(int dx, int dy) { _x += dx; _y += dy; } @Override public String toString() { return "Point(" + _x + ", " + _y + ")"; } /** The height of displayed {@link Point}s. */ private final static int HEIGHT = 10; /** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */ private final static int WIDTH = Point.HEIGHT; @Override public Shape getShape() { return new Ellipse2D.Float((float) getX() - Point.WIDTH / 2, (float) getY() - Point.HEIGHT / 2, (float) Point.HEIGHT, (float) Point.WIDTH); } }
-
ShapeFigureElement.java
package figures; import java.awt.*; import java.awt.geom.*; public abstract class ShapeFigureElement implements FigureElement { @Override public abstract void move(int dx, int dy); public abstract Shape getShape(); @Override public Rectangle getBounds() { return getShape().getBounds(); } @Override public boolean contains(Point2D p) { return getShape().contains(p); } public Color getLineColor() { return Color.black; } public Color getFillColor() { return Color.red; } @Override public final void paint(Graphics2D g2) { Shape shape = getShape(); g2.setPaint(getFillColor()); g2.fill(shape); g2.setPaint(getLineColor()); g2.draw(shape); } }
-
SlothfulPoint.java
package figures; import java.awt.*; import java.awt.geom.*; /** * This class makes mistakes to be caught by invariant checkers. */ public class SlothfulPoint extends ShapeFigureElement { private int _x; private int _y; public SlothfulPoint(int x, int y) { } public int getX() { return _x; } public int getY() { return _y; } public void setX(int x) { } public void setY(int y) { } @Override public void move(int dx, int dy) { System.out.println("Slothful moving"); } @Override public String toString() { return "SlothfulPoint"; } @Override public Shape getShape() { return new Ellipse2D.Float((float) _x, (float) _y, 1.0f, 1.0f); } }
-
[4- Tạo AspectJ Project]
-
Trước hết tạo một Project thông thường, lấy tên là
**AspectJTutorial**.
-
-
Nhấn phải chuột vào Project, chọn
**Configure/Convert to AspectJ Project**.
-
-
**Convert**thành công:
-
-
[5- Ví dụ đầu tiên bắt đầu với AspectJ]
-
Trước hết chúng ta làm một ví dụ đầu tiên, trước khi bắt đầu với các khái niệm:
-
Tạo class
**HelloAspectJDemo**:
-
HelloAspectJDemo.java
package org.o7planning.tutorial.aspectj.helloaspectj; public class HelloAspectJDemo { public static void sayHello() { System.out.println("Hello"); } public static void greeting() { String name = new String("John"); sayHello(); System.out.print(name); } public static void main(String[] args) { sayHello(); System.out.println("--------"); sayHello(); System.out.println("--------"); greeting(); } }
-
Một class như trên là hoàn toàn không có gì đáng chú ý, tuy nhiên đặt ra vấn đề bạn muốn chương trình làm một cái gì đó ngay trước, hoặc ngay sau khi phương thức
**được gọi, chẳng hạn in ra màn hình câu thông báo. Theo cách truyền thống bạn sẽ thêm vào một dòng lệnh in ra màn hình ngay trước khi gọi** *sayHello()* *.* **sayHello()**
-
-
**AspectJ**là một hướng lập trình khía cạnh (aspect programming), nó cho bạn một giải pháp khác để giải quyết vấn đề này, tất nhiên **AspectJ**còn làm được nhiều hơn thế. Hãy nhớ đây chỉ là ví dụ **HelloWorld**.
-
**File/New/Other..**
-
-
-
-
Một file có tên:
**HelloAspectJ.aj**đã được tạo ra, nó có cấu trúc khá giống với một class.
-
**AspectJ**các phiên bản trước kia sử dụng **Annotation**để mô tả, các phiên bản gần đây mới đưa vào file ***.aj**. Trong tài liệu này tôi bỏ qua không sử dụng Annotation, vì nó không rõ ràng bằng việc sử dụng file ***.aj**. Ngoài ra file ***.aj**có ngữ pháp giống một class, **eclipse**sẽ thông báo giúp bạn ngữ pháp viết sai.
-
-
Sửa code của
**HelloAspectJ.aj**:
-
HelloAspectJ.aj
package org.o7planning.tutorial.aspectj.helloaspectj; public aspect HelloAspectJ { // Định nghĩa ra một pointcut. // call: gọi method sayHello() của class HelloAspectJDemo pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); before() : callSayHello() { System.out.println("Before call sayHello"); } after() : callSayHello() { System.out.println("After call sayHello"); } }
-
**AspectJ**có chút khác biệt với một class thông thường nó thêm vào rất nhiều các từ khóa. Và file có đuôi là ***.aj**chứ không phải là ***.java**. Một số từ khóa của **AspectJ**:
-
- aspect pointcut privileged call execution
- initialization preinitialization handler get set
- staticinitialization target args within withincode
- cflow cflowbelow annotation before after around
- proceed throwing returning adviceexecution declare
- parents warning error soft precedence thisJoinPoint
- thisJoinPointStaticPart thisEnclosingJoinPointStaticPart
- issingleton perthis pertarget percflow percflowbelow
- pertypewithin lock unlock thisAspectInstance
-
-
Quay trở lại với ví dụ
**HelloWorld**. Bây giờ chúng ta chạy class **HelloAspectJDemo**. Và kết quả nhận được:
-
-
**AspectJ**là vô cùng mạnh mẽ. Chẳng hạn với ví dụ trên nếu bạn sửa lại code trên **HelloAspectJ.aj**một chút có thể làm cho nó có tác dụng trên mọi class gọi hàm **sayHello()**.
-
// Định nghĩa ra một pointcut. // call: gọi method sayHello() của class HelloAspectJDemo pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); // Sửa lại thành: // Có nghĩa là mọi nơi (class, aspectj) gọi sayHello() pointcut callSayHello(): call(* *.sayHello());
-
[6- Các khái niệm cơ bản trong AspectJ]
-
Trong
**AspectJ**bạn cần phân biệt một số khái niệm:
-
- Advice
- Pointcut
- JoinPoint
-
-
### 6.1- JoinPoint
-
**JoinPoint**(Điểm tham gia) là một điểm được xác định rõ ràng trong dòng chảy của chương trình
-
- Chúng ta muốn thi hành một đoạn code (“advice”) mỗi lần gặp điểm
**JoinPont**.
- Chúng ta không muốn làm lộn xộn code bằng việc chỉ rõ ràng “Đây là các điểm tham gia”
- Nghĩa là không tự viết code vào các vị trí đó.
**AspectJ**cung cấp một cú pháp để chỉ ra những **JoinPoint**"từ bên ngoài" mã thực tế.
- Đánh dấu chúng lại rồi thực thi code nào đó viết bên ngoài.
- Chúng ta muốn thi hành một đoạn code (“advice”) mỗi lần gặp điểm
-
**JoinPoint**là một điểm trong dòng chảy chương trình "Nơi một cái gì đó sẽ xảy ra", cái gì ở đây có thể là:
-
- Nơi method được gọi
- Nơi một ngoại lệ đã ném ra
- Nơi biến được truy cập (accessed)
- Nơi khởi tạo một đối tượng
- Nơi tham chiếu tới một đối tượng.
-
Như vậy
**JoinPoint**rất đa dạng, vị trí bạn khởi tạo một đối tượng thì đó cũng coi là một **JoinPoint**.
-
Quay lại với ví dụ
**HelloWorld**chúng ta sẽ xác định một số **JoinPoint**:
-
-
### 6.2- PointCut
-
Định nghĩa
**Pointcut**bao gồm một bên trái và một bên phải, cách nhau bằng dấu hai chấm
-
- Phía bên trái bao gồm các tên
**pointcut**và các tham số **pointcut**(chẳng hạn, các dữ liệu có sẵn khi các sự kiện xảy ra)
- Bên phải chứa bản thân
**Pointcut**
- Phía bên trái bao gồm các tên
-
**Ví dụ:**
-
pointcut callSayHello(): call(* HelloAspectJDemo.sayHello());
-
- Tên của Pointcut là
**callSayHello**
- Pointcut này không có tham số
- Bản thân Pointcut là
**call(* HelloAspectJDemo.sayHello())**
- Pointcut này đề cập đến bất kỳ thời điểm nào phương thức
**HelloAspectJDemo.sayHello()**được gọi.
- Tên của Pointcut là
-
-
### 6.3- Advice
-
Quay trở lại với ví dụ
**HelloWorld**, chúng ta có 2 advice
-
- before()
- after()
-
-
**Advice**(Tư vấn hoặc lời khuyên) xác định một hành vi. Các đoạn code của một **Advice**sẽ được chạy ở mọi điểm tham gia (Join point) **Pointcut**. Chính xác cách thức mã này được chạy phụ thuộc vào loại **Advice**(loại tư vấn).
-
**AspectJ**hỗ trợ ba loại Advice. Các loại Advice xác định nó tương tác như thế nào với các JoinPoint (điểm tham gia) nó được định nghĩa. Vì vậy AspectJ chia ra before (chạy trước) JoinPoint, after (chạy sau) JoinPoint, và around (chạy tại chỗ hoặc "xung quanh") JoinPoint.
-
Trong khi
**"before Advice"**là tương đối không có vấn đề, với **"after Advice"**có 3 tình huống: Sau khi thực hiện của một **JoinPoint**hoàn thành bình thường, sau khi ném một ngoại lệ, hoặc sau khi thực hiện một trong hai. AspectJ cho phép **"after Advice"**cho bất kỳ hai tình huống này.
-
- TODO: Giải thích thêm
**"around Advice"**.
- TODO: Giải thích thêm
-
Để dễ hiểu chúng ta xem một vài ví dụ với
**Advice**:
-
HelloAspectJ2.aj
package org.o7planning.tutorial.aspectj.helloaspectj; public aspect HelloAspectJ2 { pointcut callSayHello(): call(* HelloAspectJDemo.sayHello()); // Advice loại "after returning". after() returning (Object retObj): callSayHello() { System.out.println("Returned normally with " + retObj); } // Advice loại "after throwing". after() throwing (Exception e): callSayHello() { System.out.println("Threw an exception: " + e); } // Bao gồm cả 2 tình huống trả về bình thường // Hoặc bị ngoại lệ khi gọi method (sayHello) after() : callSayHello() { System.out.println("Returned or threw an Exception"); } }
-
Loại Advice
*có thể không cần quan tâm tới giá trị trả về (của method) lúc đó có có thể viết.* **"after returning"**
-
// Advice loại "after returning". // Quan tâm tới giá trị trả về after() returning (Object retObj): callSayHello() { System.out.println("Returned normally with " + retObj); } // Advice loại "after returning" không cần quan tâm tới Object trả về. after() returning(): callSayHello() { System.out.println("Returned normally"); } // Hoặc // Advice loại "after returning" không cần quan tâm tới Object trả về. after() returning : callSayHello() { System.out.println("Returned normally"); }
-
-
[7- Ví dụ AspectJ cơ bản]
-
Trước khi đi vào chi tiết nâng cao, chúng ta xem các ví dụ cơ bản, và các quy tắc trong
**AspectJ**, nếu không hiểu được các quy tắc này bạn không thể hiểu được **AspectJ**.
-
-
### 7.1- Quy tắc mô tả class, method, * và ..
-
Trong
**AspectJ**nếu bạn muốn nhắc tới một lớp, một phương thức trong khai báo Pointcut bạn cần phải ghi tên đầy đủ của nó. Ví dụ:
-
- figures.Point
- figures.Point.setX(int)
-
Trường hợp class và AspectJ cùng trong một package thì bạn có thể ghi một cách ngắn gọn. Ví dụ:
-
- Point
- Point.setX(int)
-
Hãy xem một ví dụ minh họa dưới đây,
**AspectJ01.aj**và class **Point**nằm trong 2 package khác nhau.
-
-
AspectJ01.aj
package org.o7planning.tutorial.aspectj.demo01; public aspect AspectJ01 { // Class Point và AspectJ này không cùng package // vì vậy phải ghi rõ cả package (Bắt buộc). // Pointcut này định nghĩa các điểm tham gia (JoinPoint) // chỉ trong phạm vi class ClassTest01 // ClassTest01 và AspectJ này cùng package, // vì vậy có thể bỏ qua package trong within. pointcut callSetX() : call(void figures.Point.setX(int)) && within (ClassTest01) ; // Advice before() : callSetX() { System.out.println("Before call Point.setX(int)"); } }
-
ClassTest01.java
package org.o7planning.tutorial.aspectj.demo01; import figures.Point; public class ClassTest01 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.setX(20); System.out.println("---- (2) ----"); point.setY(100); System.out.println("---- (3) ----"); } }
-
Kết quả chạy lớp
**ClassTest01**:
-
-
Như vậy tại đây có một số ghi chú:
-
// within sử dụng để hạn chế phạm vi của Pointcut // trong trường hợp dưới đây // Chỉ chứa các điểm tham gia (JoinPoint) trong class ClassTest01. within (ClassTest01) // Có thể sử dụng import import figures.Point; ..... // Và có thể viết ngắn gọn. pointcut callSetX() : call(void Point.setX(int)) && within (ClassTest01) ;
-
Dấu * trong AspectJ
-
// Tập hợp các JoinPont gọi method Point.setX(int) với package bất kỳ. pointcut callSetX() : call(void *.Point.setX(int)) ; // Tập hợp các Pointcut gọi Point.setX(int) với package bất kỳ // và kiểu trả về bất kỳ. pointcut callSetX() : call(* *.Point.setX(int)) ; // Pointcut gọi các method tĩnh setX(int) của một class có tên *Point (APoint, AbcPoint,...) // và thuộc package sample, kiểu trả về int. pointcut callSetX() : call(public static int sample.*Point.setX(int)) ; // Sử dụng (..) để mô tả method có 0 hoặc nhiều tham số. pointcut callSetX() : call(public static int sample.*Point.setX(..)) ;
-
### 7.2- Target & args
-
**target**: Là đối tượng tham gia tại JoinPoint (Điểm tham gia), đối tượng gọi method(hoặc đối tượng truy cập field).
**args**: Là tham số.
Hãy xem ví dụ minh họa:
-
AspectJ02.aj
package org.o7planning.tutorial.aspectj.demo02; // Đã import class Point. import figures.Point; public aspect AspectJ02 { // Pointcut, khi gọi Point.move(int,int) // Sử dụng target để khai báo đối tượng tham gia // Sử dụng args để khai báo các tham số. // within để hạn chế các JoinPoint chỉ trong class ClassTest02. pointcut callMove(Point point, int dx, int dy) : call(* figures.Point.move(int,int)) && args(dx,dy) && target(point) && within(ClassTest02) ; before(Point point, int dx, int dy) : callMove(point, dx, dy ) { System.out.println("Before call move(" + dx + "," + dy + ")"); System.out.println(point.toString()); } }
-
ClassTest02.java
package org.o7planning.tutorial.aspectj.demo02; import figures.Point; public class ClassTest02 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.move(20, 30); System.out.println("---- (2) ----"); System.out.println(point.toString()); System.out.println("---- (3) ----"); point.setX(100); } }
-
-
Kết quả chạy ví dụ
-
-
### 7.3- Toán tử && ||
-
AspectJ03.aj
package org.o7planning.tutorial.aspectj.demo03; // Chú ý: Phải import FigureElement & Point import figures.FigureElement; import figures.Point; public aspect AspectJ03 { // Pointcut gồm các hành động di chuyển (move) pointcut moveAction() : ( call(void FigureElement.move(int,int)) || call(void Point.setX(int)) || call(void Point.setY(int)) ) && within (ClassTest03); before() : moveAction() { System.out.println("before move"); } }
-
ClassTest03.java
package org.o7planning.tutorial.aspectj.demo03; import figures.FigureElement; import figures.Line; import figures.Point; public class ClassTest03 { public static void main(String[] args) { Point point = new Point(10, 200); System.out.println("---- (1) ----"); point.setX(20 ); System.out.println("---- (2) ----"); FigureElement line= new Line(new Point(1,1), new Point(10,10)); line.move(10, 10); System.out.println("---- (3) ----"); } }
-
Kết quả chạy ví dụ
-
-
### 7.4- Field trong AspectJ
-
FieldInAspectJ.aj
package org.o7planning.tutorial.aspectj.demo04; import java.io.PrintStream; public aspect FieldInAspectJ { // Field in AspectJ. PrintStream logStream = System.err; pointcut move() : call(* figures.Point.move(int,int)) && within(FieldInAspectJTest); before(): move() { logStream.println("Before Point move"); } }
-
FieldInAspectJTest.java
package org.o7planning.tutorial.aspectj.demo04; import figures.Point; public class FieldInAspectJTest { public static void main(String[] args) { Point point = new Point(10, 200); System.err.println("---- (1) ----"); point.setX(20); System.err.println("---- (2) ----"); point.move(10, 10); System.err.println("---- (3) ----"); } }
-
Kết quả chạy ví dụ:
-
-
### 7.5- Khai báo kiểu nội bộ (Inter-type declarations)
-
PointObserving.aj
package org.o7planning.tutorial.aspectj.demo05; import java.util.ArrayList; import java.util.List; import figures.Point; public aspect PointObserving { // Class Point hoàn toàn không có field: observers // Tuy nhiên vẫn có thể khai báo tại đây. // observers: Ghi lại các vị trí điểm thay đổi. private List<Point> Point.observers = new ArrayList<Point>(); pointcut moveAction(Point point) : call(void Point.move(int,int) ) && target(point) && within(PointObservingTest); after(Point point) : moveAction(point) { System.out.println("Point moved"); // Thêm vào vị trí mới. point.observers.add(point); // Ghi ra các vị trí của điểm đã đi qua. System.out.println(" - "+point.observers); } public static void addObserver(Point p) { // p.observers.add(s); } public static void removeObserver(Point p) { // p.observers.remove(s); } }
-
PointObservingTest.java
package org.o7planning.tutorial.aspectj.demo05; import figures.Point; public class PointObservingTest { public static void main(String[] args) { Point point1 = new Point(100, 100); // Di chuyển lần 1 point1.move(10, 10); // Di chuyển lần 2 point1.move(10, 10); System.out.println("----------------------"); Point point2 = new Point(200, 200); // Di chuyển lần 1 point2.move(15, 10); // Di chuyển lần 2 point2.move(15, 10); // Di chuyển lần 3 point2.move(25, 10); } }
-
Kết quả chạy ví dụ:
-
-
### 7.6- Tracking
-
**Tracking**: Nghĩa là theo dấu vết (Các phương thức nào đã được gọi và lần lượt thế nào, hoặc diễn biến của cái gì đó ...)
-
Chúng ta sẽ tạo một
**Aspect**, nó định nghĩa một **pointcut**chứa các điểm tham gia là các nơi mà phương thức thực thi, và cũng tạo một **Advice**để định nghĩa đoạn code sẽ được thực thi tại các vị trí đó.
-
SimpleTracing.aj
package org.o7planning.tutorial.aspectj.demo06; import org.aspectj.lang.Signature; public aspect SimpleTracing { // Tập hợp các JoinPoint tại vị trí gọi method bất kỳ. // và nằm trong class SimpleTracingTest. pointcut tracedCall() : call (* *(..)) // && !within(SimpleTracing) && within(SimpleTracingTest) ; before() : tracedCall() { Signature sig = thisJoinPointStaticPart.getSignature(); String line = "" + thisJoinPointStaticPart.getSourceLocation().getLine(); String sourceName = thisJoinPointStaticPart.getSourceLocation() .getWithinType().getCanonicalName(); // System.out.println("Call from " + sourceName + " line " + line + "\n to " + sig.getDeclaringTypeName() + "." + sig.getName() +"\n"); } }
-
SimpleTracingTest.java
package org.o7planning.tutorial.aspectj.demo06; import figures.Point; public class SimpleTracingTest { private static void testMethod1() { Point point = new Point(100, 100); point.setX(100); } private static void testMethod2() { String text = "This is text"; String s = text.substring(2); System.out.println(s); } public static void main(String[] args) { testMethod1(); testMethod2(); } }
-
Kết quả chạy ví dụ:
-
-
Ví dụ trên tôi giới hạn việc ghi ra thông tin các method được gọi bên trong code của class
**SimpleTrackingTest**. Nếu bạn bỏ điều kiện để loại bỏ các **JoinPoint**trên chính aspect **SimpleTracking**, điều này là cần thiết để tránh một vòng lặp vô tận.
-
### 7.7- Cflow
-
Luồng điều khiển (control flow) là luồng các điểm thực hiện của chương trình bên trong của một điểm tham gia (JointPoint) cụ thể.
**cflow()**và **cflowbelow()**được tạo ra để tóm lấy các điểm tham gia khác như là một thông số và cho phép chúng ta định nghĩa một luồng điều khiển dựa trên pointcut - pointcuts này sẽ tóm tất cả các điểm tham gia trong luồng điều khiển của từng Joinpoint cụ thể.
-
**cflow()**sẽ tóm lấy tất cả các điểm tham gia (join point) như **call**, **execution**, **set**và **get**field, **error handlers**trong luồng điều khiển của một **JointPont**cụ thể.
-
Hình minh họa dưới đây chứa các JointPoint gọi phương thức
**MyClass.callA()**.
-
-
Sử dụng
**cflow(..)**:
-
-
-
Xem ví dụ chi tiết:
-
-
CflowAspectJ.aj
package org.o7planning.tutorial.aspectj.demo07; public aspect CflowAspectJ { pointcut call_cflow_callA() : cflow( call( * MyClass.callA() ) ) && within(CFlowDemo || MyClass); before() : call_cflow_callA() { System.out.println( "Join Point at: " + thisJoinPointStaticPart.getSourceLocation().getWithinType().getCanonicalName() + " --> " + thisJoinPointStaticPart.getSourceLocation().getLine()); } }
-
MyClass.java
package org.o7planning.tutorial.aspectj.demo07; public class MyClass { public void callA() { callB(); callC(); } public void callB() { callC(); } public void callC() { } }
-
CFlowDemo.java
package org.o7planning.tutorial.aspectj.demo07; public class CFlowDemo { public static void main(String[] args) { MyClass myClass= new MyClass(); myClass.callA(); myClass.callA(); } }
-
Kết quả chạy class
**CFlowDemo**:
-
-
### 7.8- Cflowbelow
-
Luồng điều khiển (control flow) là luồng các điểm thực hiện của chương trình bên trong của một điểm tham gia (JointPoint) cụ thể.
**cflow()**và **cflowbelow()**được tạo ra để tóm lấy các điểm tham gia khác như là một thông số và cho phép chúng ta định nghĩa một luồng điều khiển dựa trên pointcut - pointcuts này sẽ tóm tất cả các điểm tham gia trong luồng điều khiển của từng Joinpoint cụ thể.
-
**cflowbelow()**có hành vi giống với **cflow**, nhưng nó không tóm điểm tham gia trong tham số của nó, và tóm tất cả các điểm tham gia còn lại.
-
Bạn có thể xem thêm ở mục
**cflow()**.
-
-

Set-Cookie: ezCMPCCS=true; Path=/; Domain=o7planning.org; Expires=Thu, 19 Sep 2019 11:17:08 GMT

PageSpeed: off

Vary: Accept-Encoding,X-APP-JSON

X-Frame-Options: DENY

Cache-Control: max-age=0, must-revalidate, no-cache, no-store

Server: cloudflare


text:
OB
Home
Về OBook
Login / Register
Đăng nhập bằng Facebook
hoặc
Đăng nhập bằng Google
Khánh Huyềnn
Timeline
Thư viện
Đang theo dõi
0
Thông tin
phường 7, Quận 11, Hồ Chí Minh, Vietnam
1
quyển sách
Qui định thư viện
Chủ sách chưa cập nhật quy định
Khánh Huyềnn
đã thêm 1 sách vào thư viện
Điều kỳ diệu của tiệm tạp hóa Namiya
by Higashino Keigo
14 reviews
Có 27 chủ sách đang sở hữu sách này trên OBook, bạn có thể
Mượn sách
Đổi sách
Gửi
Liên hệ
Về OBook
Điều khoản
Riêng tư
Bạn cần đăng nhập để thực hiện hành động này.
Đăng nhập bằng Facebook
hoặc
Đăng nhập bằng Google

WARC-Type: response

Content-Type: application/http; msgtype=response

WARC-Identified-Payload-Type: text/html

Server: nginx/1.10.0 (Ubuntu)

Content-Type: text/html; charset=utf-8

X-Crawler-Transfer-Encoding: chunked

Connection: keep-alive

Vary: Accept-Encoding

X-Frame-Options: SAMEORIGIN

X-XSS-Protection: 1; mode=block

X-Content-Type-Options: nosniff

Cache-Control: max-age=0, private, must-revalidate

Strict-Transport-Security: max-age=15552000; includeSubDomains

X-Crawler-Content-Encoding: gzip


text:
Tổng:
0
Xem giỏ hàng
Toggle navigation
Trang chủ
Giới thiệu
Sản phẩm
Trang Sức Bạc Nam
-
Nhẫn Bạc Nam
(
105
)
-
Dây Chuyền Bạc Nam
(
252
)
-
Lắc Tay Bạc Nam
(
39
)
-
Mặt Dây Chuyền Bạc Nam
(
47
)
Trang Sức Bạc Nữ
-
Nhẫn Bạc Nữ
(
240
)
-
Dây Chuyền Bạc Nữ
(
573
)
-
Vòng Tay Bạc Nữ
(
265
)
-
Lắc Chân Bạc Nữ
(
154
)
-
Bông Tai Bạc Nữ
(
215
)
-
Kiềng Bạc Đeo Cổ
(
91
)
-
Mặt Dây Chuyền Bạc Nữ
(
3
)
-
Bộ Trang Sức Bạc Nữ
(
325
)
Trang Sức Bạc Trẻ Em
-
Dây Chuyền Bạc Trẻ Em
(
69
)
-
Bông Tai Bạc Trẻ Em
(
35
)
-
Kiềng Bạc Trẻ Em
(
3
)
-
Vòng Tay Bạc Trẻ Em
(
143
)
-
Lắc Chân Bạc Trẻ Em
(
0
)
-
Nhẫn Bạc Trẻ Em
(
12
)
-
Bộ Trang Sức Bạc Trẻ Em
(
18
)
Trang Sức Bạc Đôi
-
Nhẫn Đôi Bạc
(
59
)
-
Dây Chuyền Đôi Bạc
(
0
)
Trang Sức Phong Thủy
Phụ Kiện Bạc
Trang Sức Vàng Nam
-
Nhẫn Vàng Nam
(
0
)
-
Dây Chuyền Vàng Nam
(
5
)
-
Lắc Tay Vàng Nam
(
0
)
-
Mặt Dây Chuyền Vàng Nam
(
0
)
Trang Sức Vàng Nữ
-
Nhẫn Vàng Nữ
(
1
)
-
Dây Chuyền Vàng Nữ
(
12
)
-
Vòng Tay Vàng Nữ
(
5
)
-
Lắc Chân Vàng Nữ
(
1
)
-
Bông Tai Vàng Nữ
(
4
)
-
Mặt Dây Chuyền Vàng Nữ
(
0
)
-
Kiềng Vàng Nữ
(
0
)
-
Bộ Trang Sức Vàng Nữ
(
4
)
Trang Sức Vàng Trẻ Em
-
Dây Chuyền Vàng Trẻ Em
(
0
)
-
Bông Tai Vàng Trẻ Em
(
0
)
Hỏi đáp
Tin tức
Trang chủ
Liên hệ với trang sức vàng bạc PTJ
LIÊN HỆ PTJ
Thông tin liên hệ
Làng Nghề Vàng Bạc Lương Ngọc
Xã Thúc Kháng - Huyện Bình Giang - Tỉnh Hải Dương
Điện Thoại: 0977.9377.97
Email: contact@ptj.vn
VUI LÒNG ĐIỀN ĐẦY ĐỦ THÔNG TIN BÊN DƯỚI
Họ và tên: (
*
)
Địa chỉ: (
*
)
Điện thoại: (
*
)
Email :
Nội Dung: (
*
)
Gửi Thông Tin
×

Server: Apache

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Pragma: no-cache

Connection: Upgrade, close

Content-Type: text/html; charset=UTF-8


markdown:
# (Q&A) Đại lý bảo hiểm là gì, họ hoạt động như thế nào?
Câu hỏi: Đại lý bảo hiểm là gì, họ hoạt động như thế nào?
Trả lời:
Điều 84 Luật KDBH quy định đại lý là người đưa sản phẩm bảo hiểm đến tận tay người có yêu cầu bảo hiểm. Họ hoạt động trong phạm vi ủy quyền của DNBH được thể hiện trong hợp đồng đại lý ký kết giữa DNBH và đại lý bảo hiểm:
“Đại lý bảo hiểm là tổ chức, cá nhân được doanh nghiệp bảo hiểm uỷ quyền trên cơ sở hợp đồng đại lý bảo hiểm để thực hiện hoạt động đại lý bảo hiểm theo quy định của Luật này và các quy định khác của pháp luật có liên quan.”
Điều 85 Luật KDBH quy định: “Đại lý bảo hiểm có thể được doanh nghiệp bảo hiểm uỷ quyền tiến hành các hoạt động sau đây:
1. Giới thiệu, chào bán bảo hiểm;
2. Thu xếp việc giao kết hợp đồng bảo hiểm;
3. Thu phí bảo hiểm;
4. Thu xếp giải quyết bồi thường, trả tiền bảo hiểm khi xảy ra sự kiện bảo hiểm;
5. Thực hiện các hoạt động khác có liên quan đến việc thực hiện hợp đồng bảo hiểm.”
Như vậy, đại lý bảo hiểm hoạt động nhân danh doanh nghiệp bảo hiểm và mang
lại lợi ích cho doanh nghiệp bảo hiểm nhưng chỉ được làm những công việc mà doanh nghiệp bảo hiểm cho phép đã được nêu trong hợp đồng đại lý bảo hiểm.

Server: nginx

Vary: Cookie

X-F-Cache: BYPASS

X-Signature: KUSANAGI

X-Proxy-Cache: MISS


text:
-
Combo bọt làm sạch răng miệng 2 in 1 splat và cây cạo lưỡi
260,000 vnđ
-
Combo Nước Súc Miệng Thanh Hương Plus & Máy Tăm Nước Cầm Tay Waterpik Cordless Plus Wp 450
3,120,000 vnđ
3,000,000 vnđ-4%
-
Combo đặc trị hôi miệng TheraBreath Oral Rinse – Giúp lấy lại hơi thở thơm mát
290,000 vnđ
210,000 vnđ-28%
-
Combo 2 Bàn chải kẽ răng - Loại trừ vi khuẩn gây Hôi Miệng
160,000 vnđ
-
Combo 2 Chai xịt khử mùi hôi miệng AL01
320,000 vnđ
290,000 vnđ-9%
-
Combo 2 Nước súc miệng THERABREATH PLUS
1,120,000 vnđ
1,010,000 vnđ-10%
-
Combo Thanh Hương Tán & Nước súc miệng Therabreath Plus
910,000 vnđ
820,000 vnđ-10%
-
Combo: Mua 4 hộp Trà Thơm Miệng tặng ngay 1 hộp
340,000 vnđ
-
Combo Thanh Hương Tán & Bàn chải kẽ răng
435,000 vnđ
390,000 vnđ-10%
-
Combo Thanh Hương Tán Plus & Trà Thơm Miệng
635,000 vnđ
575,000 vnđ-9%
-
Combo Thanh Hương Tán & Trà Thơm Miệng
435,000 vnđ
390,000 vnđ-10%

markdown:
-
[Combo bọt làm sạch răng miệng 2 in 1 splat và cây cạo lưỡi](/san-pham-combo/combo-bot-lam-sach-rang-mieng-2-in-1-splat-va-cay-cao-luoi.html)
260,000 vnđ
-
[Combo Nước Súc Miệng Thanh Hương Plus & Máy Tăm Nước Cầm Tay Waterpik Cordless Plus Wp 450](/san-pham-combo/combo-nuoc-suc-mieng-thanh-huong-plus-may-tam-nuoc-cam-tay-waterpik-cordless-plus-wp-450.html)
3,120,000 vnđ
3,000,000 vnđ-4%
-
[Combo đặc trị hôi miệng TheraBreath Oral Rinse – Giúp lấy lại hơi thở thơm mát](/san-pham-rang-mieng/combo-dac-tri-hoi-mieng-therabreath-oral-rinse-giup-lay-lai-hoi-tho-thom-mat.html)
290,000 vnđ
210,000 vnđ-28%
-
[Combo 2 Bàn chải kẽ răng - Loại trừ vi khuẩn gây Hôi Miệng](/san-pham-rang-mieng/combo-5-ban-chai-ke-rang-loai-tru-vi-khuan-gay-hoi-mieng.html)
160,000 vnđ
-
[Combo 2 Chai xịt khử mùi hôi miệng AL01](/san-pham-rang-mieng/thuoc-xit-khu-mui-hoi-mieng-al01.html)
320,000 vnđ
290,000 vnđ-9%
-
[Combo 2 Nước súc miệng THERABREATH PLUS](/san-pham-combo/combo-2-nuoc-suc-mieng-therabreath-plus.html)
1,120,000 vnđ
1,010,000 vnđ-10%
-
[Combo Thanh Hương Tán & Nước súc miệng Therabreath Plus](/san-pham-combo/combo-thanh-huong-tan-nuoc-suc-mieng-therabreath-plus.html)
910,000 vnđ
820,000 vnđ-10%
-
[Combo: Mua 4 hộp Trà Thơm Miệng tặng ngay 1 hộp](/san-pham-combo/combo-4-tra-thom-mieng.html)
340,000 vnđ
-
[Combo Thanh Hương Tán & Bàn chải kẽ răng](/san-pham-combo/combo-thanh-huong-tan-plus-ban-chai-ke-rang.html)
435,000 vnđ
390,000 vnđ-10%
-
[Combo Thanh Hương Tán Plus & Trà Thơm Miệng](/san-pham-combo/combo-thanh-huong-tan-plus-tra-thom-mieng.html)
635,000 vnđ
575,000 vnđ-9%
-
[Combo Thanh Hương Tán & Trà Thơm Miệng](/san-pham-combo/combo-thanh-huong-tan-tra-thom-mieng.html)
435,000 vnđ
390,000 vnđ-10%

Vary: Accept-Encoding,User-Agent

Keep-Alive: timeout=2, max=100

Connection: Keep-Alive

Content-Type: text/html


text:
Số sim: 096.1369.279
Giá: 2.950.000 ₫
Loại sim: Sim Tiến Đơn
Mọi thông tin mua bán vui lòng liên hệ hotline để đặt sim và mua sim đúng cách, khách hàng vui lòng gọi điện trước khi đặt sim. Xin cảm ơn!
Đăng ngày: 19/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Hỗ Trợ 24/7

markdown:
Số sim: 096.1369.279
Giá: 2.950.000 ₫
Loại sim: Sim Tiến Đơn
Mọi thông tin mua bán vui lòng liên hệ hotline để đặt sim và mua sim đúng cách, khách hàng vui lòng gọi điện trước khi đặt sim. Xin cảm ơn!
|Sim số đẹp||Mạng||Giá||Loại sim||Đặt mua|
|
|
Đăng ngày: 19/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Đăng ngày: 18/09/2018
Hỗ Trợ 24/7

Cache-Control: no-store, no-cache, must-revalidate


text:
Trong ảnh "Em bé napalm", cô bé Kim Phúc cùng một số trẻ em Việt Nam vừa khóc vừa chạy sau khi bom napalm dội xuống .
Bài viết đặt một câu hỏi - rất hiển nhiên - mà cũng rất cay đắng, vì sao cái gọi là nạn nhân chiến tranh xâm lược của Đế Quốc Mỹ, cuối cùng đã tìm cách đào thoát và được giúp tị nạn ở phương Tây, chứ không ở lại Việt Nam. Nạn nhân đó cũng không muốn được hưởng vinh quang như một biểu tượng chống chiến tranh. Và rồi cô Kim Phúc, nhân vật chính trong bức ảnh đó, có hài lòng cho cuộc đời trở thành điểm tựa đẹp nhất cho quân đội miền Bắc Việt Nam hay không?
Sự thật là năm 1992, cô Kim Phúc đã thoát khỏi Việt Nam, tị nạn ở Canada để không biến mình thành công cụ tuyên truyền cho một phía. Cũng như tác giả Đức Hồng đặt lên một câu hỏi rất đáng chú ý rằng năm 1972, những người lính Cộng sản Bắc Việt đang làm gì ở đất của miền Nam trong một hiệp định phân chia đất nước vẫn còn hiệu lực, và vì sao “Các em nhỏ ấy lại chạy về phía lính Việt Nam Cộng Hòa để kêu cứu mà không một chút sợ sệt, sao các em không chọn những người lính Cộng sản Bắc Việt cũng đang lẩn trốn ở ngay gần đó?”
Nhà nhiếp ảnh Nick Út (đầu tiên ở bên phải) trong chuyến đi về Việt Nam tháng 6/2015.Sự thật ít người biết là gia đình cô Kim Phúc cũng bị đánh tư sản vào năm 1975. Cả nhà sống rất khó khăn. Năm 1982 khi một phóng viên Đức đến Việt Nam để tìm lại nhân vật lịch sử trong bức ảnh “em bé Napalm” thi Phúc bị ép trở thành một nhân vật tuyên truyền. Mọi thời gian sinh hoạt của cô Kim Phúc đều bị công an kiểm soát chặt chẽ. Thậm chí Kim Phúc bị buộc thôi học trường đại học Y khoa ở Sài Gòn, về sống ở quê Trảng Bàng để tiện dễ kiểm soát ngôn ngữ tuyên truyền. Sau đó, khi lấy chồng là một du học sinh sống ở Cuba, nhân một chuyến đi, máy bay ngừng chặng ở Gander, Newfoundland (Canada), Kim Phúc cùng chồng trốn khỏi sự kiểm soát của công an viên đi kèm và xin tị nạn. Mọi sự kiện này không là lời kể miệng, mà được bày tỏ công khai trên trang web riêng của Kim Phúc tên là Kim Foundation, quỹ từ thiện do cô sáng lập và cũng như trong quyền hồi kí The Girl in the Picture.
Cùng với những câu hỏi của tác giả Đức Hồng, cũng có một câu hỏi khác được đặt ra, là một người phóng viên của AP, vì sao từ vị trí là một nhiếp ảnh gia ghi chép sự kiện một cách trung dung, ông Nick Út dần dần biến mình thành một người quảng bá sai ý nghĩa của bức ảnh, biến mình thành một nhân vật tuyên truyền?
Trong cuộc tranh cãi về sự kiện ông Níck Út trở lại Việt Nam lần này, họa sĩ Trịnh Cung nêu một ý kiến khác: “Nếu là một phóng viên có đạo đức, Nick Út đã phải có một thái độ khác. Trái lại, ông Út đã biến cơ hội giữ lại khoảng khắc thương đau của một sinh mệnh, tạo hào quang cho mình, mà không đứng về sự thật của nạn nhân trong suốt nhiều năm liền”. Họa sĩ Trịnh Cung nói: “Giả sử khi được trao giải Pulitzer, ông Nick từ chối và trao tặng cho nạn nhân mà ông chụp được, có lẽ ông đã giải bày được một cách khiêm tốn về cơ may - hơn là tài năng - và tỏa sáng gấp bội lần hơn lúc này”.
Nhưng điều quan trọng là bên cạnh sự thật ít ai biết về cô Kim Phúc khi phải đào thoát sang Canada - trong số ít đó có ông Nick - thì dường như ông cũng tảng lờ việc đứng về phía nỗi khổ và khó khăn của cô Kim Phúc, và chỉ bám chặt vào bề mặt bức ảnh để nuôi ánh hào quang cho mình, phản bội lại đạo đức nghề nghiệp báo chí, là phải nói thật về điều mình thấy. Đạo đức nghề nghiệp đó, đã được chứng minh như chuyện nhà nhiếp ảnh Eddie Adams với bức ảnh chấn động thế giới về tướng Nguyễn Ngọc Loan khi bắn phục binh Bắc Việt Bảy Lốp vào năm 1968. Sau khi biết được sự thật, nhất là khi nghe tin tướng Loan qua đời, Eddie Adamas đã nói với báo chí rằng ông đã rất hối hận vì bức ảnh đó làm hại một tướng quân và làm hại một chế độ.
Đạo đức con người cũng đã được thể hiện, khi diễn viên Jane Fonda đi ra miền Bắc Việt Nam cổ vũ cho cuộc chiến tranh tương tàn vào năm 1972. Nhiều năm sau, nhiều lần, người diễn viên này đã bày tỏ sự hối hận vô bờ bến về hành động của mình khi biết rõ mọi chuyện. Thậm chí năm 2015, bà Jane Fonda lập lại lời xin lỗi đến các cựu chiến binh Mỹ một lần nữa về bức ảnh đó, ngay sau khi có chuyện kể rằng vào gần ngày 30-4, một cựu binh Mỹ gặp bà ở ngoài đường đã nhổ nước miếng xuống đất và mắng “bitch”. Nhưng Nick thì không. Đặc biệt sẽ càng không lâu hơn nữa, khi gần đây, có người đưa lên trên mạng các bức ảnh cho thấy ông đứng selfie cạnh tượng đồng của lãnh tụ lừng danh của đảng CSVN, ông Hồ Chí Minh. Dù có thể việc selfie đó chỉ nhằm làm trơn tru cho việc triển lãm ảnh chiến tranh Việt Nam của AP, cũng như việc ra sách của ông Nick trong nước.
Chắc chắn trong các buổi ra sách, và ký tặng, ông Nick cũng sẽ không nói gì về sự thật sau bức ảnh của cô Kim Phúc, và cũng sẽ im lặng như một sự tán đồng với hệ thống truyên truyền Nhà nước rằng đó chính là bức ảnh tố cáo tội ác xâm lược của đế quốc Mỹ. Ngẫm nghĩ riêng và đôi khi lại thấy chạnh lòng cho nhà nhiếp ảnh của nhà nước Việt Nam, ông Đoàn Công Tính. Khác với ông Nick Út, ông Đoàn Công Tính là một nhà nhiếp ảnh chiến trường thật sự và lăn lộn với tất cả những hình ảnh mà ông ta có được. Thực tế là ông Tính không có ý định tham gia Pulitzer hay hoạt động nhiếp ảnh gì của bọn phương Tây tư bản phản động cả. Ông chỉ có tinh thần trong sáng của một nhà nhiếp ảnh nỗ lực phục vụ theo mệnh lệnh và ông cố gắng làm tốt mọi thứ.
Phan Thị Kim Phúc và bức ảnh “định mệnh” tại Salt Lake City.
Gần đây, việc phát hiện ông thay nền khác cho đẹp hơn trong một bức ảnh chiến tranh nổi tiếng của ông, thật ra chỉ là một trong những ý định tiếp tục làm đẹp nhất phần công việc tuyên truyền theo chỉ đạo của mình, mà suốt đời ông đã phục vụ trung thành. Về một ý nghĩa nào đó, Đoàn Công Tính không có lỗi, thậm chí đáng khen ngợi. Sai lầm ở đây là giới nhiếp ảnh phương Tây đã háo hức chọn ông Tính để đưa ông vào một môi trường khác mà ông không hề có kinh nghiệm, cũng ông Tính cũng không hình dung rồi mình sẽ ra sao. Những nhà nhiếp ảnh chiến tranh phương Tây thật sự trở thành những kẻ ngốc nghếch khi không hiểu rằng nhiếp ảnh phục vụ tuyên truyền ở Việt Nam, cũng như nhiều nước xã hội chủ nghĩa khác là có thể làm mọi thứ, miễn sao đạt mục đích. Trong khi đó, nhiếp ảnh phương Tây cần giá trị nguyên gốc của sự kiện. Khác biệt về môi trường và con người rất rõ.
Đặt sai vị trí, có thể làm hỗn loạn nhiều thứ trong dòng chảy thời gian của con người. Như bức ảnh của Eddie Adams hay của Jane Fonda chẳng hạn. Nếu để nguyên giá trị của ông Đoàn Công Tính trong thời đại và môi trường phụng sự Đảng và Nhà nước - ông sẽ mãi mãi tỏa sáng và đáng ngưỡng mộ. Cũng như ông Nick Út sẽ mãi mãi tỏa sáng với bức ảnh “Em bé Napalm” trong sự im lặng thỏa hiệp và lừa dối của ông. Nếu để ca ngợi, tôi sẽ chọn ông Đoàn Công Tính, vì ông Tính không có gì khác ngoài “sự thật” mà ông chân thành phô bày với tất cả mọi người. Dù trơ trẽn nhưng ít ra ông đã làm tốt bổn phận bề tôi của mình.
Tuấn Khanh

markdown:
*Trong ảnh "Em bé napalm", cô
bé Kim Phúc cùng một số trẻ em Việt Nam vừa khóc vừa chạy sau khi bom
napalm dội xuống .*
Bài viết đặt một câu hỏi - rất hiển nhiên - mà cũng rất cay đắng, vì sao cái gọi là nạn nhân chiến tranh xâm lược của Đế Quốc Mỹ, cuối cùng đã tìm cách đào thoát và được giúp tị nạn ở phương Tây, chứ không ở lại Việt Nam. Nạn nhân đó cũng không muốn được hưởng vinh quang như một biểu tượng chống chiến tranh. Và rồi cô Kim Phúc, nhân vật chính trong bức ảnh đó, có hài lòng cho cuộc đời trở thành điểm tựa đẹp nhất cho quân đội miền Bắc Việt Nam hay không?
Sự
thật là năm 1992, cô Kim Phúc đã thoát khỏi Việt Nam,
tị nạn ở Canada
để không biến mình thành công cụ tuyên truyền cho một phía. Cũng như tác giả
Đức Hồng đặt lên một câu hỏi rất đáng chú ý rằng năm 1972, những người lính
Cộng sản Bắc Việt đang làm gì ở đất của miền Nam trong một hiệp định phân chia
đất nước vẫn còn hiệu lực, và vì sao “C
*ác
em nhỏ ấy lại chạy về phía lính Việt Nam Cộng Hòa để kêu cứu mà không một chút
sợ sệt, sao các em không chọn những người lính Cộng sản Bắc Việt cũng đang lẩn
trốn ở ngay gần đó?*”
Sự
thật ít người biết là gia đình cô Kim Phúc cũng bị đánh tư sản vào năm 1975. Cả
nhà sống rất khó khăn. Năm 1982 khi một phóng viên Đức đến Việt Nam để
tìm lại nhân vật lịch sử trong bức ảnh “
*Nhà nhiếp ảnh Nick Út (đầu tiên ở bên phải) trong
chuyến đi về Việt Nam
tháng 6/2015.*
Cùng với những câu hỏi của tác giả Đức Hồng, cũng có một câu hỏi khác được đặt ra, là một người phóng viên của AP, vì sao từ vị trí là một nhiếp ảnh gia ghi chép sự kiện một cách trung dung, ông Nick Út dần dần biến mình thành một người quảng bá sai ý nghĩa của bức ảnh, biến mình thành một nhân vật tuyên truyền?
Trong
cuộc tranh cãi về sự kiện ông Níck Út trở lại Việt Nam lần này, họa sĩ Trịnh Cung nêu
một ý kiến khác: “
*Nếu là một phóng viên
có đạo đức, Nick Út đã phải có một thái độ khác. Trái lại, ông Út đã biến cơ
hội giữ lại khoảng khắc thương đau của một sinh mệnh, tạo hào quang cho mình,
mà không đứng về sự thật của nạn nhân trong suốt nhiều năm liền*”. Họa sĩ Trịnh
Cung nói: “ *Giả sử khi được trao giải
Pulitzer, ông Nick từ chối và trao tặng cho nạn nhân mà ông chụp được, có lẽ
ông đã giải bày được một cách khiêm tốn về cơ may - hơn là tài năng - và tỏa
sáng gấp bội lần hơn lúc này*”.
Nhưng điều quan trọng là bên cạnh sự thật ít ai biết về cô Kim Phúc khi phải đào thoát sang Canada - trong số ít đó có ông Nick - thì dường như ông cũng tảng lờ việc đứng về phía nỗi khổ và khó khăn của cô Kim Phúc, và chỉ bám chặt vào bề mặt bức ảnh để nuôi ánh hào quang cho mình, phản bội lại đạo đức nghề nghiệp báo chí, là phải nói thật về điều mình thấy. Đạo đức nghề nghiệp đó, đã được chứng minh như chuyện nhà nhiếp ảnh Eddie Adams với bức ảnh chấn động thế giới về tướng Nguyễn Ngọc Loan khi bắn phục binh Bắc Việt Bảy Lốp vào năm 1968. Sau khi biết được sự thật, nhất là khi nghe tin tướng Loan qua đời, Eddie Adamas đã nói với báo chí rằng ông đã rất hối hận vì bức ảnh đó làm hại một tướng quân và làm hại một chế độ.
Đạo
đức con người cũng đã được thể hiện, khi diễn viên Jane Fonda đi ra miền Bắc
Việt Nam
cổ vũ cho cuộc chiến tranh tương tàn vào năm 1972. Nhiều năm sau, nhiều lần,
người diễn viên này đã bày tỏ sự hối hận vô bờ bến về hành động của mình khi
biết rõ mọi chuyện. Thậm chí năm 2015, bà Jane Fonda lập lại lời xin lỗi đến
các cựu chiến binh Mỹ một lần nữa về bức ảnh đó, ngay sau khi có chuyện kể rằng
vào gần ngày 30-4, một cựu binh Mỹ gặp bà ở ngoài đường đã nhổ nước miếng xuống
đất và mắng “
*bitch*”. Nhưng Nick thì không.
Đặc biệt sẽ càng không lâu hơn nữa, khi gần đây, có người đưa lên trên mạng các
bức ảnh cho thấy ông đứng selfie cạnh tượng đồng của lãnh tụ lừng danh của đảng
CSVN, ông Hồ Chí Minh. Dù có thể việc selfie đó chỉ nhằm làm trơn tru cho việc
triển lãm ảnh chiến tranh Việt Nam
của AP, cũng như việc ra sách của ông Nick trong nước.
Chắc chắn trong các buổi ra sách, và ký tặng, ông Nick cũng sẽ không nói gì về sự thật sau bức ảnh của cô Kim Phúc, và cũng sẽ im lặng như một sự tán đồng với hệ thống truyên truyền Nhà nước rằng đó chính là bức ảnh tố cáo tội ác xâm lược của đế quốc Mỹ. Ngẫm nghĩ riêng và đôi khi lại thấy chạnh lòng cho nhà nhiếp ảnh của nhà nước Việt Nam, ông Đoàn Công Tính. Khác với ông Nick Út, ông Đoàn Công Tính là một nhà nhiếp ảnh chiến trường thật sự và lăn lộn với tất cả những hình ảnh mà ông ta có được. Thực tế là ông Tính không có ý định tham gia Pulitzer hay hoạt động nhiếp ảnh gì của bọn phương Tây tư bản phản động cả. Ông chỉ có tinh thần trong sáng của một nhà nhiếp ảnh nỗ lực phục vụ theo mệnh lệnh và ông cố gắng làm tốt mọi thứ.
* Phan Thị Kim Phúc và bức ảnh “định mệnh” tại Salt Lake
City.*
Gần đây, việc phát hiện ông thay nền khác cho đẹp hơn trong một bức ảnh chiến tranh nổi tiếng của ông, thật ra chỉ là một trong những ý định tiếp tục làm đẹp nhất phần công việc tuyên truyền theo chỉ đạo của mình, mà suốt đời ông đã phục vụ trung thành. Về một ý nghĩa nào đó, Đoàn Công Tính không có lỗi, thậm chí đáng khen ngợi. Sai lầm ở đây là giới nhiếp ảnh phương Tây đã háo hức chọn ông Tính để đưa ông vào một môi trường khác mà ông không hề có kinh nghiệm, cũng ông Tính cũng không hình dung rồi mình sẽ ra sao. Những nhà nhiếp ảnh chiến tranh phương Tây thật sự trở thành những kẻ ngốc nghếch khi không hiểu rằng nhiếp ảnh phục vụ tuyên truyền ở Việt Nam, cũng như nhiều nước xã hội chủ nghĩa khác là có thể làm mọi thứ, miễn sao đạt mục đích. Trong khi đó, nhiếp ảnh phương Tây cần giá trị nguyên gốc của sự kiện. Khác biệt về môi trường và con người rất rõ.
Đặt
sai vị trí, có thể làm hỗn loạn nhiều thứ trong dòng chảy thời gian của con
người. Như bức ảnh của Eddie Adams hay của Jane Fonda chẳng hạn. Nếu để nguyên
giá trị của ông Đoàn Công Tính trong thời đại và môi trường phụng sự Đảng và
Nhà nước - ông sẽ mãi mãi tỏa sáng và đáng ngưỡng mộ. Cũng như ông Nick Út sẽ
mãi mãi tỏa sáng với bức ảnh “
*Em bé
Napalm*” trong sự im lặng thỏa hiệp và lừa dối của ông. Nếu để ca ngợi, tôi
sẽ chọn ông Đoàn Công Tính, vì ông Tính không có gì khác ngoài “ *sự thật*” mà ông chân thành phô bày với
tất cả mọi người. Dù trơ trẽn nhưng ít ra ông đã làm tốt bổn phận bề tôi của
mình.
Tuấn Khanh

Set-Cookie: fn.gzip=1;expires=Tue, 19 Sep 2028 11:37:03 GMT;path=/

Cache-Control: no-cache

Vary: Accept-Encoding,Cookie


text:
Chào bạn. Cảm ơn bạn đã quan tâm và gửi câu hỏi tới chuyên mục tư vấn của Thu Cúc Clinics. Nhu cầu xóa hình xăm đang ngày càng tăng cao và việc lựa chọn địa chỉ xóa hình xăm nào để đảm bảo an toàn cũng là nỗi băn khoăn của rất nhiều người. Đối với một số thắc mắc của bạn, chúng tôi xin được giải đáp cụ thể như sau:
Xóa hình xăm ở Bình Dương nên đến địa chỉ nào?
Tràn lan các cơ sở xóa hình xăm ở Bình Dương
Hiện nay, nắm bắt được nhu cầu muốn xóa bỏ hình xăm của đông đảo khách hàng, có rất nhiều các cơ sở xóa hình xăm mọc tràn lan khắp tỉnh Bình Dương kéo theo chất lượng dịch vụ không được đảm bảo. Tại một số cơ sở xóa hình xăm kém chất lượng có sử dụng các loại kem xóa hình xăm có chứa thành phần lột tẩy mạnh, gây bào mòn cho làn da. Hơn nữa, tại các cơ sở xóa hình xăm không uy tín thì cơ sở vật chất và trang thiết bị phục vụ cho việc xóa hình xăm không đảm bảo nên dễ gây viêm nhiễm cho làn da vùng điều trị.
Do vậy, để đảm bảo an toàn và có được hiệu quả xóa hình xăm tối ưu, lời khuyên của các chuyên gia là bạn nên đến các cơ sở uy tín và áp dụng xóa hình xăm bằng công nghệ hiện đại. Để lựa chọn, bạn nên tìm hiểu những cơ sở xóa hình xăm có lịch sử hoạt đông lâu năm, được Bộ Y tế cấp giấy phép hoạt động, hội tụ đội ngũ chuyên gia giỏi. Điều quan trọng nữa là các cơ sở xóa hình xăm đó phải được trang bị cơ sở vật chất tiện nghi cùng công nghệ xóa hình xăm hiện đại.
Lựa chọn xóa hình xăm tại Thu Cúc Clinics Sài Gòn
Mặc dù chưa có cơ sở xóa hình xăm ở Bình Dương nhưng nếu đang có nhu cầu muốn xóa bỏ hình xăm, bạn có thể lựa chọn di chuyển tới các cơ sở Thu Cúc Clinics Sài Gòn. Tại đây đang ứng dụng phương pháp xóa hình xăm bằng công nghệ Laser Yag – một trong những công nghệ hiện đại nhất hiện nay. Phương pháp này tại Thu Cúc Clinics cũng đã được FDA Hoa Kì kiểm định độ an toàn.
Máy Laser YAG có khả năng phát ra các tia hồng ngoại với bước sóng có xung độ ngắn khoảng 10 phần tỉ giây (10 nanosecond) cùng hộp nhuộm Q-Tune sẽ phá vỡ mực xăm dưới da một cách hiệu quả nhất. Ánh sáng tia laser này phù hợp để xóa các sắc tố trong da, tẩy sạch các vết xăm cũng như sửa chữa các khiếm khuyết của các đường xăm hỏng, đặc biệt là xăm mí mắt, xăm cung mày mà không đau, không để lại sẹo.
Như vậy. bên cạnh việc lựa chọn xóa hình xăm ở Bình Dương, bạn có thể di chuyển tới Thu Cúc Clinics để được xóa hình xăm an toàn và hiệu quả. Mọi thông tin thắc mắc bạn có thể gọi điện trực tiếp tới tổng đài 1900 5588 96 để được các chuyên viên tư vấn cụ thể.

markdown:
Chào bạn. Cảm ơn bạn đã quan tâm và gửi câu hỏi tới chuyên mục tư vấn của Thu Cúc Clinics. Nhu cầu xóa hình xăm đang ngày càng tăng cao và việc lựa chọn địa chỉ xóa hình xăm nào để đảm bảo an toàn cũng là nỗi băn khoăn của rất nhiều người. Đối với một số thắc mắc của bạn, chúng tôi xin được giải đáp cụ thể như sau:
**Xóa hình xăm ở Bình Dương nên đến địa chỉ nào?**
### Tràn lan các cơ sở xóa hình xăm ở Bình Dương
![Nhu cầu xóa hình xăm ở Bình Dương đang ngày càng tăng cao do rất nhiều nguyên nhân khách quan. Nhu cầu xóa hình xăm ở Bình Dương đang ngày càng tăng cao do rất nhiều nguyên nhân khách quan.](https://thucucclinics.com.vn/wp-content/uploads/2018/05/xoa-hinh-xam-o-can-tho.jpg)
Nhu cầu xóa hình xăm đang ngày càng tăng cao do rất nhiều nguyên nhân khách quan.
Hiện nay, nắm bắt được nhu cầu muốn xóa bỏ hình xăm của đông đảo khách hàng, có rất nhiều các cơ sở xóa hình xăm mọc tràn lan khắp tỉnh Bình Dương kéo theo chất lượng dịch vụ không được đảm bảo. Tại một số cơ sở xóa hình xăm kém chất lượng có sử dụng các loại kem xóa hình xăm có chứa thành phần lột tẩy mạnh, gây bào mòn cho làn da. Hơn nữa, tại các cơ sở xóa hình xăm không uy tín thì cơ sở vật chất và trang thiết bị phục vụ cho việc xóa hình xăm không đảm bảo nên dễ gây viêm nhiễm cho làn da vùng điều trị.
![Hiện có rất nhiều các cơ sở xóa hình xăm mọc tràn lan khắp tỉnh Bình Dương kéo theo chất lượng dịch vụ không được đảm bảo. Hiện có rất nhiều các cơ sở xóa hình xăm mọc tràn lan khắp tỉnh Bình Dương kéo theo chất lượng dịch vụ không được đảm bảo.](https://thucucclinics.com.vn/wp-content/uploads/2018/05/xoa-hinh-xam-tai-thai-nguyen.jpg)
Hiện có rất nhiều các cơ sở xóa hình xăm mọc tràn lan khắp tỉnh Bình Dương kéo theo chất lượng dịch vụ không được đảm bảo.
Do vậy, để đảm bảo an toàn và có được hiệu quả xóa hình xăm tối ưu, lời khuyên của các chuyên gia là bạn nên đến các cơ sở uy tín và áp dụng xóa hình xăm bằng công nghệ hiện đại. Để lựa chọn, bạn nên tìm hiểu những cơ sở xóa hình xăm có lịch sử hoạt đông lâu năm, được Bộ Y tế cấp giấy phép hoạt động, hội tụ đội ngũ chuyên gia giỏi. Điều quan trọng nữa là các cơ sở xóa hình xăm đó phải được trang bị cơ sở vật chất tiện nghi cùng công nghệ xóa hình xăm hiện đại.
### Lựa chọn xóa hình xăm tại Thu Cúc Clinics Sài Gòn
![Thu Cúc Clinics là địa chỉ xóa hình xăm được đông đảo khách hàng khắp mọi nơi tin chọn. Thu Cúc Clinics là địa chỉ xóa hình xăm được đông đảo khách hàng khắp mọi nơi tin chọn.](https://thucucclinics.com.vn/wp-content/uploads/2018/04/lam-sao-xoa-hinh-xam-nhanh-va-hieu-qua-4.jpg)
Thu Cúc Clinics là địa chỉ xóa hình xăm được đông đảo khách hàng khắp mọi nơi tin chọn.
Mặc dù chưa có cơ sở xóa hình xăm ở Bình Dương nhưng nếu đang có nhu cầu muốn xóa bỏ hình xăm, bạn có thể lựa chọn di chuyển tới các cơ sở Thu Cúc Clinics Sài Gòn. Tại đây đang ứng dụng phương pháp xóa hình xăm bằng công nghệ Laser Yag – một trong những công nghệ hiện đại nhất hiện nay. Phương pháp này tại Thu Cúc Clinics cũng đã được FDA Hoa Kì kiểm định độ an toàn.
![Laser Yag tẩy sạch các vết xăm cũng như sửa chữa các khiếm khuyết của các đường xăm hỏng. Laser Yag tẩy sạch các vết xăm cũng như sửa chữa các khiếm khuyết của các đường xăm hỏng.](https://thucucclinics.com.vn/wp-content/uploads/2018/04/giai-phap-xoa-hinh-xam-tren-co-the-hieu-qua-4.jpg)
Laser Yag tẩy sạch các vết xăm cũng như sửa chữa các khiếm khuyết của các đường xăm hỏng.
Máy Laser YAG có khả năng phát ra các tia hồng ngoại với bước sóng có xung độ ngắn khoảng 10 phần tỉ giây (10 nanosecond) cùng hộp nhuộm Q-Tune sẽ phá vỡ mực xăm dưới da một cách hiệu quả nhất. Ánh sáng tia laser này phù hợp để xóa các sắc tố trong da, tẩy sạch các vết xăm cũng như sửa chữa các khiếm khuyết của các đường xăm hỏng, đặc biệt là xăm mí mắt, xăm cung mày mà không đau, không để lại sẹo.
Như vậy. bên cạnh việc lựa chọn xóa hình xăm ở Bình Dương, bạn có thể di chuyển tới Thu Cúc Clinics để được xóa hình xăm an toàn và hiệu quả. Mọi thông tin thắc mắc bạn có thể gọi điện trực tiếp tới tổng đài 1900 5588 96 để được các chuyên viên tư vấn cụ thể.


text:
Loading...
- Hoạt động cuối:
- 4/7/16
- Tham gia ngày:
- 4/7/16
- Bài viết:
- 0
- Đã được thích:
- 0
- Điểm thành tích:
- 0
Đang theo dõi 2
- Giới tính:
- Nam
- Sinh nhật:
- 18/3/89 (Age: 29)
Chia sẻ trang này
thuantony
Nam, 29
- thuantony được nhìn thấy lần cuối:
- 4/7/16
-
- Đang tải...
-
Giới thiệu
- Giới tính:
- Nam
- Sinh nhật:
- 18/3/89 (Age: 29)
Tương tác

markdown:
Loading...
![ thuantony](https://timbantinh.us/styles/novus/xenforo/avatars/avatar_male_l.png)
- Hoạt động cuối:
- 4/7/16
- Tham gia ngày:
- 4/7/16
- Bài viết:
- 0
- Đã được thích:
- 0
- Điểm thành tích:
[0](members/69848/trophies)
###
Đang theo dõi
[2](members/69848/following)
- Giới tính:
- Nam
- Sinh nhật:
- 18/3/89 (Age: 29)
### Chia sẻ trang này
# thuantony
Nam, 29
- thuantony được nhìn thấy lần cuối:
- 4/7/16
-
- Đang tải...
-
### Giới thiệu
- Giới tính:
- Nam
- Sinh nhật:
- 18/3/89 (Age: 29)
### Tương tác

Cache-control: private, max-age=0

Set-Cookie: xf_session=a2f334c3b9364e913772847c5bba9f22; path=/; secure; httponly


text:
Loading...
- Hoạt động cuối:
- 21/11/16
- Tham gia ngày:
- 21/11/16
- Bài viết:
- 0
- Đã được thích:
- 0
- Điểm thành tích:
- 0
- Giới tính:
- Nam
- Sinh nhật:
- 12/11/86 (Age: 31)
Chia sẻ trang này
hoavangmaydo
Nam, 31
- hoavangmaydo được nhìn thấy lần cuối:
- 21/11/16
-
- Đang tải...
-
Giới thiệu
- Giới tính:
- Nam
- Sinh nhật:
- 12/11/86 (Age: 31)
Tương tác

markdown:
Loading...
![ hoavangmaydo](https://timbantinh.us/styles/novus/xenforo/avatars/avatar_male_l.png)
- Hoạt động cuối:
- 21/11/16
- Tham gia ngày:
- 21/11/16
- Bài viết:
- 0
- Đã được thích:
- 0
- Điểm thành tích:
[0](members/74699/trophies)
- Giới tính:
- Nam
- Sinh nhật:
- 12/11/86 (Age: 31)
### Chia sẻ trang này
# hoavangmaydo
Nam, 31
- hoavangmaydo được nhìn thấy lần cuối:
- 21/11/16
-
- Đang tải...
-
### Giới thiệu
- Giới tính:
- Nam
- Sinh nhật:
- 12/11/86 (Age: 31)
### Tương tác

Set-Cookie: xf_session=5f9b2f3f913275ae7ee89acba1a55aff; path=/; secure; httponly


text:
Tiết lộ 5 món quà lưu niệm nên mua khi du lịch Ý
Continue Reading
Nếu bạn đang băn khoăn không biết đâu là món quà lưu niệm nên mua khi du lịch Ý thì…
Nếu bạn đang băn khoăn không biết đâu là món quà lưu niệm nên mua khi du lịch Ý thì…
Đất nước Italia xinh đẹp nổi tiếng với nhiều di tích đổ nát mang tính biểu tưởng của thành Rome,…
1. Thức ăn đường phố Bạn có thể dễ dàng tìm thấy và thưởng thức hương vị ngon tuyệt của…
Hãy cùng khám phá sự quyến rũ không thể cưỡng nổi của thành phố Delhi, từ vườn hoa, khung cảnh…
Trong các bài viết trước, mình đã trình bày đôi nét về lịch sử đền Taj Mahal, một trong những…
Khách sạn Trident chỉ cách lâu đài Taj Mahal đúng 1 dặm đường. Vì thế, khách sạn Trident là nơi…
Taj Mahal được xem là một trong những công trình kiến trúc lãng mạn và lộng lẫy nhất thế giới.…

markdown:
[Du lịch](http://timhieuthegioi.com/category/du-lich), [Italia](http://timhieuthegioi.com/category/italia) [Tiết lộ 5 món quà lưu niệm nên mua khi du lịch Ý](http://timhieuthegioi.com/du-lich/5-mon-qua-luu-niem-nen-mua-khi-du-lich-y.html) [](http://timhieuthegioi.com/du-lich/5-mon-qua-luu-niem-nen-mua-khi-du-lich-y.html)
Nếu bạn đang băn khoăn không biết đâu là món quà lưu niệm nên mua khi du lịch Ý thì…
[Continue Reading](http://timhieuthegioi.com/du-lich/5-mon-qua-luu-niem-nen-mua-khi-du-lich-y.html)
Nếu bạn đang băn khoăn không biết đâu là món quà lưu niệm nên mua khi du lịch Ý thì…
Đất nước Italia xinh đẹp nổi tiếng với nhiều di tích đổ nát mang tính biểu tưởng của thành Rome,…
1. Thức ăn đường phố Bạn có thể dễ dàng tìm thấy và thưởng thức hương vị ngon tuyệt của…
Hãy cùng khám phá sự quyến rũ không thể cưỡng nổi của thành phố Delhi, từ vườn hoa, khung cảnh…
Trong các bài viết trước, mình đã trình bày đôi nét về lịch sử đền Taj Mahal, một trong những…
Khách sạn Trident chỉ cách lâu đài Taj Mahal đúng 1 dặm đường. Vì thế, khách sạn Trident là nơi…
Taj Mahal được xem là một trong những công trình kiến trúc lãng mạn và lộng lẫy nhất thế giới.…

Set-Cookie: __cfduid=d24b3450829c49be18f6daf35e77916dd1537357686; expires=Thu, 19-Sep-19 11:48:06 GMT; path=/; domain=.timhieuthegioi.com; HttpOnly

Vary: X-Forwarded-Proto,Accept-Encoding


text:
Việc buôn bán chim trời ở chợ Thạnh Hóa (tỉnh Long An) đã diễn ra từ nhiều năm nay nhưng cơ quan chức năng vẫn làm lơ mặc cho người dân buôn bán công khai. Đáng nói, địa điểm này dường như đang trở nên một nét văn hóa…thúc đẩy phát triển du lịch ở vùng quê này.
Rất nhiều người biết đến chợ Thạnh Hóa (Long An) là chợ chim trời “lớn nhất miền Tây”. Tại đây, rất nhiều loại chim được bày bán như chằng nghịch, cò, vịt trời, cu đất,…Thậm chí, đến các loại chim quý hiếm như: điên điển, giang sen, trích cồ, đại bàng…cũng được bày bán công khai.
Dịp cận Tết, chợ chim trời càng thêm “hút” khách. Một khách hàng tên Hưng (ở Bình Chánh, TP.HCM) lặn lội hàng chục cây số (km) để về đây lùng mua một số loại chim trời về ăn… tất niên.
“Chim trời ở đây cũng có giá phải chăng, chẳng hạn cò có giá 50.000 đồng/con, mua số lượng nhiều được giảm còn 40-45 nghìn đồng/con. Loại này mua rồi nhờ chủ quán “khò” cho vàng, mang về nấu măng hoặc xào với mướp hương thì tuyệt. Ở đây, chim, cò tự nhiên chứ trên thành phố, giá vừa đắt, có khi lại là hàng không bảo đảm chất lượng”, anh Hưng nói.
Rất nhiều khách du lịch khi đi ngang qua đây đều ghé vào chợ chim trời Thạnh Hóa. Dễ dàng bắt gặp nhiều ô tô mang biển số TP.HCM về đây mua chim trời về… nhậu. Theo các du khách này, việc ghé chợ Thạnh Hóa tham quan vì nghe nói đây là “chợ chim lớn nhất miền Tây”.
Theo chị T, một chủ quán bán chim trời ở chợ Thạnh Hóa, đa số các mặt hàng được bày bán tại chợ nông sản Thạnh Hóa đều có nguồn gốc từ Campuchia.
“Các loại cò, vạc hoặc loại rắn thông thường như bông súng, hổ hành… thì có thể thu gom tại Việt Nam chứ các loại rùa, rắn cao cấp thì đa số nhập từ Campuchia. Chỉ cần đặt cọc trước thì bao nhiêu cũng có”, chị T cho biết.
Cũng theo chị T, những loại chim còn sống nhốt lồng thì thường dính bẫy sập, bẫy lưới; còn loại đã chết thì có thể do dính bẫy cần treo cổ, thậm chí là dính lưỡi câu (lưỡi câu cá) khiến chim đứt cổ họng.
Từng con chim, cò được cột chặt treo ngược lên trên, nhiều con được nhổ lông sẵn nằm thoi thóp chờ chết, những loại rắn, rùa,… được một số tiểu thương “vô tư” bày bán, công khai chào mời khách đang là thực trạng diễn ra hàng ngày tại chợ nông sản Thạnh Hóa, tỉnh Long An.

markdown:
** Việc buôn bán chim trời ở chợ Thạnh Hóa (tỉnh Long An) đã diễn ra từ nhiều năm nay nhưng cơ quan chức năng vẫn làm lơ mặc cho người dân buôn bán công khai. Đáng nói, địa điểm này dường như đang trở nên một nét văn hóa…thúc đẩy phát triển du lịch ở vùng quê này. **
Rất nhiều người biết đến chợ Thạnh Hóa (Long An) là chợ chim trời “lớn nhất miền Tây”. Tại đây, rất nhiều loại chim được bày bán như chằng nghịch, cò, vịt trời, cu đất,…Thậm chí, đến các loại chim quý hiếm như: điên điển, giang sen, trích cồ, đại bàng…cũng được bày bán công khai.
Dịp cận Tết, chợ chim trời càng thêm “hút” khách. Một khách hàng tên Hưng (ở Bình Chánh, TP.HCM) lặn lội hàng chục cây số (km) để về đây lùng mua một số loại chim trời về ăn… tất niên.
“Chim trời ở đây cũng có giá phải chăng, chẳng hạn cò có giá 50.000 đồng/con, mua số lượng nhiều được giảm còn 40-45 nghìn đồng/con. Loại này mua rồi nhờ chủ quán “khò” cho vàng, mang về nấu măng hoặc xào với mướp hương thì tuyệt. Ở đây, chim, cò tự nhiên chứ trên thành phố, giá vừa đắt, có khi lại là hàng không bảo đảm chất lượng”, anh Hưng nói.
Rất nhiều khách du lịch khi đi ngang qua đây đều ghé vào chợ chim trời Thạnh Hóa. Dễ dàng bắt gặp nhiều ô tô mang biển số TP.HCM về đây mua chim trời về… nhậu. Theo các du khách này, việc ghé chợ Thạnh Hóa tham quan vì nghe nói đây là “chợ chim lớn nhất miền Tây”.
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-8087-2-483861.jpg)
Chim Cò ốc chuyên bắt ốc bươu vàng, đem lại rất nhiều lợi ích cho nhà nông bị tận diệt, được rao bán tại đây với giá 250 ngàn/ con (Ảnh: Quốc Hải)
Theo chị T, một chủ quán bán chim trời ở chợ Thạnh Hóa, đa số các mặt hàng được bày bán tại chợ nông sản Thạnh Hóa đều có nguồn gốc từ Campuchia.
“Các loại cò, vạc hoặc loại rắn thông thường như bông súng, hổ hành… thì có thể thu gom tại Việt Nam chứ các loại rùa, rắn cao cấp thì đa số nhập từ Campuchia. Chỉ cần đặt cọc trước thì bao nhiêu cũng có”, chị T cho biết.
Cũng theo chị T, những loại chim còn sống nhốt lồng thì thường dính bẫy sập, bẫy lưới; còn loại đã chết thì có thể do dính bẫy cần treo cổ, thậm chí là dính lưỡi câu (lưỡi câu cá) khiến chim đứt cổ họng.
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-3766-3-409683.jpg)
Cò có giá 50.000 đồng/con được nuôi “cầm hơi” bằng rắn bông súng để chờ khách
[Sài Gòn](https://tintaynguyen.com/topic/sai-gon/) ghé mua (Ảnh: Quốc Hải).
Từng con chim, cò được cột chặt treo ngược lên trên, nhiều con được nhổ lông sẵn nằm thoi thóp chờ chết, những loại rắn, rùa,… được một số tiểu thương “vô tư” bày bán, công khai chào mời khách đang là thực trạng diễn ra hàng ngày tại chợ nông sản Thạnh Hóa, tỉnh Long An.
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-8608-5-450195.jpg)
Chim Trích cồ (con non), là một loài chim quý hiếm, nhưng được bán tại đây cho những khách hàng chơi chim kiểng với giá 150 nghìn đồng/con (Ảnh: Quốc Hải)
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-2890-6-336264.jpg)
Chim Trích cồ loại lớn được bán với giá 1 triệu đồng/ con (Ảnh: Quốc Hải)
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-8525-7-403581.jpg)
Đại bàng mắt đỏ được rao bán ở đây cho những khách hàng có thú chơi chim cảnh (Ảnh: Quốc Hải)
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-5207-8-425455.jpg)
Vịt trời cũng được rao bán tập nập tại đây (Ảnh: Quốc Hải)
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120656-9980-9-396555.jpg)
Một cậu bé đang nhổ lông chim để bán cho khách hàng…(Ảnh: Quốc Hải)
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-6855-10-380001.jpg)
Le le cũng được bán với giá 200 nghìn đồng/con…
![ ](https://tintaynguyen.com/wp-content/uploads/2018/01/1517120657-2265-11-414717.jpg)
Các loại rắn cũng được bán rất nhiều tại chợ… (Ảnh: Quốc Hải)

Set-Cookie: __cfduid=d47abbe794a634facb738f479d02775c11537354132; expires=Thu, 19-Sep-19 10:48:52 GMT; path=/; domain=.tintaynguyen.com; HttpOnly


text:
Trò Chơi Trốn Tìm
CHƯƠNG 16
Sách mới
Random Post
Bạn có thể dùng phím mũi tên để lùi/sang chương. Các phím WASD cũng có chức năng tương tự như các phím mũi tên.
Bạn có thể dùng phím mũi tên để lùi/sang chương. Các phím WASD cũng có chức năng tương tự như các phím mũi tên.

markdown:
[Trò Chơi Trốn Tìm](https://trinhdinhlinh.com/sach/tro-choi-tron-tim/)
[CHƯƠNG 16](https://trinhdinhlinh.com/sach/tro-choi-tron-tim/chuong-16-151/)
## Sách mới
## Random Post
Bạn có thể dùng phím mũi tên để lùi/sang chương. Các phím WASD cũng có chức năng tương tự như các phím mũi tên.
Bạn có thể dùng phím mũi tên để lùi/sang chương. Các phím WASD cũng có chức năng tương tự như các phím mũi tên.

Vary: Accept-Encoding, Cookie

X-Fastcgi-Cache: MISS


text:
Tiết kiệm hơn với Giá Bí mật.
Tiết kiệm ngay với Giá Bí mật
Xem khách sạn tại Malaunay trên bản đồ
Đăng ký nhận thông tin khuyến mãi mới nhất của chúng tôi
Tải app và đặt phòng mọi lúc, mọi nơi
Tham gia ngay! Tích lũy 10 đêm, nhận 1 đêm miễn phí*
© 2018 Hotels.com, L.P. Mọi quyền được bảo lưu.
Hotels.com và logo Hotels.com là thương hiệu hoặc thương hiệu đã đăng ký bảo hộ của Hotels.com, LP tại Mỹ và/hoặc các quốc gia khác. Mọi thương hiệu khác thuộc quyền sở hữu của các chủ sở hữu tương ứng.
* Tìm hiểu thêm về Hotels.com™ Rewards

WARC-Identified-Payload-Type: application/xhtml+xml

Server: Application-Server

Content-Language: vi-VN

X-Hcom-Rendered-With: release

X-UA-Compatible: IE=Edge

Cache-Control: max-age=0, no-cache, no-store

Set-Cookie: bm_sz=1C9E84EE6A68DA3521ACABFD48511447~QAAQFzk3FyyUqtFlAQAAYuZm8W8bLHj+wi9xA4H/reXWBKD7qtBIqzqkGUiQtAUmPmInDf/FrSx8W4Qo6RcmfUsCOxZdtBkunv6RwykPRorKONTz+gf5C3dnEiFfOAdxNUEJiCh/9mu2/9j2buhRhrpIzlfgMf/ihQz+35qOYUyx2OXmm7A3SmvD+QS4VpE=; Domain=.hotels.com; Path=/; Expires=Wed, 19 Sep 2018 14:36:16 GMT; Max-Age=14399; HttpOnly

Content-Security-Policy: default-src 'unsafe-inline' data: about: hcom: blob: callback: chrome-error: *; script-src 'unsafe-eval' 'unsafe-inline' data: about: blob: asset: *; report-uri https://525fade5ca1b22e6c3c9f4504b6b3f68.report-uri.com/r/d/csp/enforce


text:
Tiết kiệm hơn với Giá Bí mật.
Tiết kiệm ngay với Giá Bí mật
Xem khách sạn tại Doñinos de Salamanca trên bản đồ
Đăng ký nhận thông tin khuyến mãi mới nhất của chúng tôi
Tải app và đặt phòng mọi lúc, mọi nơi
Tham gia ngay! Tích lũy 10 đêm, nhận 1 đêm miễn phí*
© 2018 Hotels.com, L.P. Mọi quyền được bảo lưu.
Hotels.com và logo Hotels.com là thương hiệu hoặc thương hiệu đã đăng ký bảo hộ của Hotels.com, LP tại Mỹ và/hoặc các quốc gia khác. Mọi thương hiệu khác thuộc quyền sở hữu của các chủ sở hữu tương ứng.
* Tìm hiểu thêm về Hotels.com™ Rewards

Set-Cookie: bm_sz=18F67AB7BE8B3EE548899E3B723F0A1E~QAAQPx6VP3QdKuxlAQAApkJn8fdrC/WRKc7NKo5F6ChhzEcbYbRSKOZRpCVsSnTYYEBXx9NaFwBD4T8lKxd/QxzWACjnsJrPMXhFMHMT6wac9zGZeAG0TQLnPA2eX9lO7DsxS2jIp/DyKJn0OGhCGf/31cwzITTwqZ13KEf4MRAdbo2qKiyMXe3w5LfvmKI=; Domain=.hotels.com; Path=/; Expires=Wed, 19 Sep 2018 14:36:40 GMT; Max-Age=14400; HttpOnly


text:
Tiết kiệm hơn với Giá Bí mật.
Tiết kiệm ngay với Giá Bí mật
Xem khách sạn tại Dolans Bay trên bản đồ
Đăng ký nhận thông tin khuyến mãi mới nhất của chúng tôi
Tải app và đặt phòng mọi lúc, mọi nơi
Tham gia ngay! Tích lũy 10 đêm, nhận 1 đêm miễn phí*
© 2018 Hotels.com, L.P. Mọi quyền được bảo lưu.
Hotels.com và logo Hotels.com là thương hiệu hoặc thương hiệu đã đăng ký bảo hộ của Hotels.com, LP tại Mỹ và/hoặc các quốc gia khác. Mọi thương hiệu khác thuộc quyền sở hữu của các chủ sở hữu tương ứng.
* Tìm hiểu thêm về Hotels.com™ Rewards

Set-Cookie: bm_sz=B9CB3E197EBECB594592C671821B5240~QAAQmhEcuMDBBetlAQAAkueJ8eIGxhHWbA/uA5SB5qBzS7BJCrSknND5h7LIDySsMeRZYQOeodIkVaoiZd1REHwoCGbgPorE71nn44uermhL3aQPeRtZWQGOgx7id36NNzSt+qA+PjGHfBkH8o9Lz/CXjEmp7NyYjj+QHyOZFXGMxHhUd5t1m0WUEaNjv6A=; Domain=.hotels.com; Path=/; Expires=Wed, 19 Sep 2018 15:14:30 GMT; Max-Age=14399; HttpOnly