@AspectJ註解驅動,基於xml檔案的配置方式
阿新 • • 發佈:2018-12-12
基於xml檔案的配置方式,使用@AspectJ註解驅動.需要引入額外的jar包,即aspectj,從官網下載即可.
aop:scoped-proxy | 代理的作用域 |
aop:aspectj-autoproxy | 開啟@AspectJ註解驅動 |
aop:config | 定義一個spring aop |
aop:advisor | 定義一個通知器 |
aop:aspect | 定義一個切面 |
aop:before |
定義前置通知 |
aop:after | 定義後置通知 |
aop:around | 定義環繞通知 |
aop:after-returning | 定義返回通知 |
aop:after-throwing | 定義異常通知 |
aop:declare-parents | 對目標物件引入新特性 |
aop:pointcut | 定義一個可複用的切點 |
目標物件的介面和類
package siye; public interface User { void work();// 使用者工作 }
package siye; public class UserImpl implements User { @Override public void work() { System.out.println("user_work"); } public int getSalary() { return 0; } public void goHome() { System.out.println("user_go_home"); } public void throwOwn() { throw new RuntimeException(); } }
對目標物件新增特性的介面和類
package siye;
public interface Animal
{
void eat();
}
package siye;
public class AnimalImpl implements Animal
{
@Override
public void eat()
{
System.out.println("animal_eat_food");
}
}
定義的切面類
package siye;
import org.aspectj.lang.ProceedingJoinPoint;
public class CustomAspect
{
public void before()
{
System.out.println("方法即將執行----advice_before");
}
public void after()
{
System.out.println("方法執行完畢----advice_after");
}
public void afterReturning()
{
System.out.println("方法正常返回---advice_afterReturning");
}
public void aroundMethod(ProceedingJoinPoint jp)
{
try
{
System.out.println("user_start_back_home");
jp.proceed();
System.out.println("user_back_home");
} catch (Throwable e)
{
}
}
public void throwException()
{
System.out.println("方法丟擲異常----advice_throwException");
}
}
xml配置檔案設定,檔名`config.xml`
<bean id="userImpl" class="siye.UserImpl" />
<bean id="aspect" class="siye.CustomAspect" />
<!--強制使用cglib代理. -->
<aop:config proxy-target-class="true">
<aop:aspect ref="aspect">
<!--定義切點. -->
<aop:pointcut
expression="execution(* *.UserImpl.work(..))" id="funWork" />
<!--前置通知. -->
<aop:before method="before" pointcut-ref="funWork" />
<!--後置通知. -->
<aop:after method="after" pointcut-ref="funWork" />
<!--環繞通知. -->
<aop:after-returning method="afterReturning"
pointcut="execution(* *.getSalary(..))" />
<!--返回通知. -->
<aop:around method="aroundMethod"
pointcut="execution(* *.goHome(..))" />
<!--異常通知. -->
<aop:after-throwing method="throwException"
pointcut="execution(* *.throwOwn(..))" />
<!--introduction_by_xml -->
<aop:declare-parents types-matching="siye.User+"
implement-interface="siye.Animal" default-impl="siye.AnimalImpl" />
</aop:aspect>
</aop:config>
測試類
package siye;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UintTest
{
public static void main(String[] args)
{
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext();
context.setConfigLocation("classpath:/siye/config.xml");
context.refresh();
/*
* 以下三種獲取bean的方式,都會報錯異常.
* 因spring aop配置的不是強制使用cglib動態代理.
*
* 設定屬性proxy-target-class="true"
* 這將強制spring aop使用cglib動態代理.
*
* 註解S2,EnableAspectJAutoProxy中,設定
* boolean proxyTargetClass() default false;
* 此屬性為true即可.
*/
// NoSuchBeanDefinitionException: No qualifying bean of type
// 'std_aop_byxml.UserImpl' available
// UserImpl userImpl = context.getBean(UserImpl.class);
// BeanNotOfRequiredTypeException: Bean named 'userImpl' is expected to be of
// type 'std_aop_byxml.UserImpl' but was actually of type
// 'com.sun.proxy.$Proxy2'
// UserImpl userImpl = context.getBean("userImpl", UserImpl.class);
// ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to
// std_aop_byxml.UserImpl
// UserImpl userImpl = (UserImpl) context.getBean("userImpl");
// userImpl.work();
UserImpl userImpl = context.getBean(UserImpl.class);
// userImpl.work(); // 測試前置和後置通知.
// userImpl.getSalary();// 測試返回通知
// userImpl.goHome();// 測試環繞通知.
// userImpl.throwOwn();// 測試異常通知.
/*
* 為目標介面的子類,引入新的特性.
*/
Animal animal = (Animal) userImpl;
animal.eat();
context.close();
}
}