基于注解的方式实现Aop
- 在业务层相应类加@component
- 写一个通知内容的切面类
写一个通知内容的切面类把横切关注点的代码抽象到切面的类中,对业务层类进行切面通知,切面类首先是一个Ioc 中的bean,即加入@Componet 注解,切面还需加入@Aspect注解
在切面类中写各种方法进行通知
在切面类中方法前定义切点,方法上加@Before("execution(* classpath.(..))"),@After(),@AfterReturning(),@AfterThrowing()注解定义切点表示前置通知、后置通知、返回通知、异常通知。切点表达式是为了找到目标类的某些方法。表达式可以重用。环绕通知包括所有通知。
比如,
@Before(“execution(public Userdao.(..))”
public void method(){...}
表示在Userdao类任意方法执行之前要执行的method方法中的内容。
在切面类的方法中声明一个类型为JoinPoint 的参数,然后能访问链接细节,如方法名和参数值
- 在配置文件中加入如下配置
<!-- 使AspectJ注解起作用:自动为匹配的类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 在调用业务层的方法时,会有自定义的通知。
基于配置文件的方式实现Aop
- 业务层相应类
- 写切面类(不需要加@Aspect@Componet注解)
- 切面类相应的方法进行通知(不需要加@Before注解定义切点)
- 写xml配置文件
<!-- 配置 bean -->
<bean id="arithmeticCalculator" class="aopPeizhiImpl.ArithmeticCalculatorImpl"></bean>
<!-- 配置切面的 bean. -->
<bean id="loggingAspect" class="aopPeizhiImpl.LoggingAspect"></bean>
<!-- 配置 AOP -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut id="pointcut" expression="execution(* aopPeizhiImpl.ArithmeticCalculator.*(int,int))" />
<!-- 配置切面及通知 -->
<aop:aspect ref="loggingAspect">
<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
<aop:after method="afterMethod" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
</aop:aspect>
</aop:config>
- 在调用业务层的方法时,会有自定义的通知。
动态代理实现Aop
public class ArithmeticCalculatorLoggingProxy {
//要代理的对象
private ArithmeticCalculator target;
public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target){
this.target = target;
}
public ArithmeticCalculator getLoggingProxy(){
//动态代理对象,在要代理对象的每个方法加了通知的内容
ArithmeticCalculator proxy = null;
//代理对象有哪一个类加载器负责加载
ClassLoader loader = target.getClass().getClassLoader();
//代理对象的类型,即其中有哪些方法
Class [] interfaces = new Class[]{ArithmeticCalculator.class};
//当调用代理对象其中的方法时,该执行的代码
InvocationHandler h = new InvocationHandler() {
//proxy:正在返回的那个代理对象.
//method:正在被调用的方法.
//args:调用方法时,传入的参数.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
//打印日志
System.out.println("invoke.."+methodName+" begin with "+Arrays.asList(args));
Object result = null;
try{
//这里写前置通知
//调用目标方法
result = method.invoke(target, args);
//这里写返回通知
}catch(Exception e){
e.printStackTrace();
//这里写异常通知
}
//这里写后置通知
//打印日志
System.out.println("The method "+methodName+"end with"+result);
return result;
}
};
proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
public class Test {
public static void main(String[] args) {
ArithmeticCalculator target = new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
System.out.println(proxy.add(1, 2));
}
}