您好,登錄后才能下訂單哦!
本文源碼:GitHub·點這里 || GitEE·點這里
AOP全稱:Aspect Oriented Programming,面向切面編程。通過預編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術。核心作用:可以對業(yè)務邏輯的各個部分進行隔離,從而使得業(yè)務邏輯各部分之間的耦合度降低,提高程序的復用性和開發(fā)效率。AOP提供了取代繼承和委托的一種新的方案,而且使用起來更加簡潔清晰,是軟件開發(fā)中的一個熱點理念。
(1)、通知類型:Advice
前置通知[Before]:目標方法被調用之前;
返回通知[After-returning]:目標方法執(zhí)行成功之后;
異常通知[After-throwing]:在目標方法拋出異常之后;
后置通知[After]:目標方法完成之后;
環(huán)繞通知[Around]:在目標方法執(zhí)行前后環(huán)繞通知;
(2)、連接點:JoinPoint
程序執(zhí)行的某一個特定位置,如類初始前后,方法的運行前后。
(3)、切點:Pointcut
連接點是指那些在指定策略下可能被攔截到的方法。
(4)、切面:Aspect
切面由切點和通知的結合。
(5)、引入:Introduction
特殊的增強,為類添加一些屬性和方法。
(6)、織入:Weaving
將增強添加到目標類的具體連接點上的過程。編譯期織入,這要求使用特殊編譯器;類裝載期織入,這要求使用特殊的類加載器;動態(tài)代理織入,在運行期為目標類添加增強生成子類的方式,Spring采用的是動態(tài)代理織入,而AspectJ采用編譯期織入和類裝載期織入。
(7)、代理:Proxy
類被AOP織入后生成一個結果類,它是融合了原類和增強邏輯的代理類。
案例基于如下類進行:
public class Book {
private String bookName ;
private String author ;
}
public interface BookService {
void addBook (Book book) ;
}
public class BookServiceImpl implements BookService {
@Override
public void addBook(Book book) {
System.out.println(book.getBookName());
System.out.println(book.getAuthor());
}
}
public class BookAopProxyFactory {
public static BookService createService() {
// 目標類
final BookService bookService = new BookServiceImpl() ;
// 切面類
final BookAspect bookAspect = new BookAspect();
/*
* 代理類:將目標類(切入點)和 切面類(通知) 結合
*/
BookService proxyBookService = (BookService) Proxy.newProxyInstance(
BookAopProxyFactory.class.getClassLoader(),
bookService.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 前執(zhí)行
bookAspect.before();
// 執(zhí)行目標類的方法
Object obj = method.invoke(bookService, args);
// 后執(zhí)行
bookAspect.after();
return obj;
}
});
return proxyBookService ;
}
}
采用字節(jié)碼增強框架cglib,在運行時創(chuàng)建目標類的子類,從而對目標類進行增強。
public class BookAopCgLibFactory {
public static BookService createService() {
// 目標類
final BookService bookService = new BookServiceImpl() ;
// 切面類
final BookAspect bookAspect = new BookAspect();
// 核心代理類
Enhancer enhancer = new Enhancer();
// 確定父類
enhancer.setSuperclass(bookService.getClass());
// 設置回調函數(shù)
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method,
Object[] args,
MethodProxy methodProxy) throws Throwable {
bookAspect.before();
Object obj = method.invoke(bookService, args);
bookAspect.after();
return obj;
}
});
BookServiceImpl proxyService = (BookServiceImpl) enhancer.create();
return proxyService ;
}
}
spring 創(chuàng)建代理對象,從spring容器中手動的獲取代理對象。
<!-- 創(chuàng)建目標類 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 創(chuàng)建切面類 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- 創(chuàng)建代理類 -->
<bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.spring.mvc.service.BookService" />
<property name="target" ref="bookService" />
<property name="interceptorNames" value="myAspect" />
</bean>
public class BookAopSpringHalf implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Method Before ...");
Object obj = methodInvocation.proceed();
System.out.println("Method After ...");
return obj;
}
}
從spring容器獲得目標類,如果配置Aop,spring將自動生成代理。
<!-- 創(chuàng)建目標類 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 創(chuàng)建切面類 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- AOP編程配置 -->
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* com.spring.mvc.service.*.*(..))"
id="myPointCut"/>
<aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>
@Test
public void test1 (){
BookService bookService = BookAopProxyFactory.createService() ;
Book book = new Book() ;
book.setBookName("Spring實戰(zhàn)");
book.setAuthor("Craig Walls");
bookService.addBook(book);
}
@Test
public void test2 (){
BookService bookService = BookAopCgLibFactory.createService() ;
Book book = new Book() ;
book.setBookName("MySQL");
book.setAuthor("Baron");
bookService.addBook(book);
}
@Test
public void test3 (){
String xmlPath = "spring-aop-half.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) context.getBean("proxyFactory");
Book book = new Book() ;
book.setBookName("紅樓夢");
book.setAuthor("曹雪芹");
bookService.addBook(book);
}
@Test
public void test4 (){
String xmlPath = "spring-aop-all.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) context.getBean("bookService");
Book book = new Book() ;
book.setBookName("西游記");
book.setAuthor("吳承恩");
bookService.addBook(book);
}
AspectJ是一個基于Java語言的AOP框架,Spring2.0以后新增了對AspectJ切點表達式支持,通過JDK5注解技術,允許直接在類中定義切面,新版本Spring框架,推薦使用AspectJ方式來開發(fā)AOP編程。
public class BookAopAspectJ {
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知:" + joinPoint.getSignature().getName());
}
public void myAfterReturning(JoinPoint joinPoint,Object ret){
System.out.println("后置通知:" + joinPoint.getSignature().getName() + " , -->" + ret);
}
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("環(huán)繞通知前");
Object obj = joinPoint.proceed();
System.out.println("環(huán)繞通知前后");
return obj;
}
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("拋出異常通知 : " + e.getMessage());
}
public void myAfter(JoinPoint joinPoint){
System.out.println("最終通知");
}
}
<!-- 創(chuàng)建目標類 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 創(chuàng)建切面類 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopAspectJ" />
<!-- 配置AOP編程 -->
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut expression="execution(* com.spring.mvc.service.impl.BookServiceImpl.*(..))" id="myPointCut"/>
<!-- 前置通知-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>
<!-- 后置通知 -->
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
<!-- 環(huán)繞通知 -->
<aop:around method="myAround" pointcut-ref="myPointCut"/>
<!-- 拋出異常 -->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
<!-- 最終通知 -->
<aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
@Test
public void test1 (){
String xmlPath = "spring-aop-aspectj-01.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) context.getBean("bookService");
Book book = new Book() ;
book.setBookName("三國演義");
book.setAuthor("羅貫中");
bookService.addBook(book);
}
<!-- 開啟類注解的掃描 -->
<context:component-scan base-package="com.spring.mvc.service.impl" />
<!-- 確定AOP注解生效 -->
<aop:aspectj-autoproxy />
<!-- 聲明切面 -->
<bean id="myAspect" class="com.spring.mvc.config.AuthorAopAspectJ" />
<aop:config>
<aop:aspect ref="myAspect" />
</aop:config>
@Component
@Aspect
public class AuthorAopAspectJ {
@Pointcut("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
private void myPointCut(){
}
@Before("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知:" + joinPoint.getSignature().getName());
}
@AfterReturning(value="myPointCut()" ,returning="ret")
public void myAfterReturning(JoinPoint joinPoint,Object ret){
System.out.println("后置通知:" +
joinPoint.getSignature().getName() + " , -->" + ret);
}
@Around(value = "myPointCut()")
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("環(huán)繞通知前");
Object obj = joinPoint.proceed();
System.out.println("環(huán)繞通知前后");
return obj;
}
@AfterThrowing(
value="execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))",
throwing="e")
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("拋出異常通知 : " + e.getMessage());
}
@After("myPointCut()")
public void myAfter(JoinPoint joinPoint){
System.out.println("最終通知");
}
}
@Test
public void test2 (){
String xmlPath = "spring-aop-aspectj-02.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
AuthorService authorService = (AuthorService) context.getBean("authorService");
System.out.println("作者:"+authorService.getAuthor());
}
GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。