版权声明:仅供学习交流使用 https://blog.csdn.net/drxRose/article/details/84801522
基于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();
}
}