代理模式是指,为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用.作用是增强功能和控制访问.分为:
静态代理:在程序运行之前已经定义好代理类,代理类和目标类要实现相同的接口
动态代理:在程序运行时才确定代理类和目标类的关系,又分为
a.JDK动态代理,要求目标对象必须实现接口
b.CGLIB动态代理,要求目标类必须能够被继承,即不是final类.它的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理类
AOP,即面向切面编程,是OOP的补充.利用AOP可以让业务逻辑和业务逻辑方法解耦合,提高了代码的可用性,大大提高了开发效率.
底层采用JDK和CGLIB动态代理实现的.
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
a.@Before前置通知
package com.aspectj.demo1;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.aspectj.common.LoggerUtil;
@Aspect
// 定义切面类,就是对业务方法进行增强
public class MyAspect {
// 前置通知
// 在目标方法执行前执行前置通知
@Before(value="execution(public * com.aspectj.demo1.SomeServiceImpl.run(..))")
public void beforeExcute(JoinPoint point) throws Exception{
System.out.println("前置通知被执行");
// 得到切入点表达式
// execution(void com.aspectj.demo1.SomeService.run())
LoggerUtil.doLog(point);
// 得到方法签名
// void com.aspectj.demo1.SomeService.run()
LoggerUtil.doLog(point.getSignature());
// 得到目标对象
// com.aspectj.demo1.SomeServiceImpl@4b5a5ed1
LoggerUtil.doLog(point.getTarget());
// 得到方法名字
// run
Signature signature = point.getSignature();
String name = signature.getName();
LoggerUtil.doLog(name);
}
}
b.@AfterReturning后置通知
package com.aspectj.demo2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
// 定义切面类,就是对业务方法进行增强
public class MyAspect {
// 后置通知
// 因为是在业务方法结束后执行,所以有返回值
// 但是增强后的值不会改变原来业务方法的返回值
@AfterReturning(value="execution(* *..SomeServiceImpl.*(..))",returning="result")
// result表示的是业务方法的返回值
public void afterReturningExecute(JoinPoint point ,Object result){
// 获取方法的名字
String name = point.getSignature().getName();
if("getName".equals(name)){
result += " end";
}
System.out.println("后置通知增强后的返回值:" + result);
}
}
c.@Around环绕通知
package com.aspectj.demo3;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {
// 环绕通知
// 在目标方法执行前后都执行
// 必须有返回值
// 可以改变原目标方法的返回值
@Around(value="execution(* *..SomeServiceImpl.getName(..))")
public Object aroundExecute(ProceedingJoinPoint point) throws Throwable{
// 得到目标方法的返回值
String result = (String) point.proceed();
result += " my";
System.out.println("环绕通知的返回值:" + result);
return result;
}
}
d.@AfterThrowing异常通知
package com.aspectj.demo4;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import com.aspectj.common.LoggerUtil;
@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {
// 异常通知
@AfterThrowing(value="execution(* *..SomeServiceImpl.run(..))",throwing="e")
public void afterThrowingExecute(Throwable e) throws Exception{
System.out.println("程序发生异常");
LoggerUtil.doLog(e);
}
}
e.@After最终通知
package com.aspectj.demo5;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
// 定义切面类,就是对业务方法进行增强
public class MyAspect {
// 最终通知
// 无论目标对象是否抛出异常,该增强都会被执行
@After(value="execution(* *..SomeServiceImpl.run(..))")
public void afterExecute(){
System.out.println("程序发生异常");
}
}
f.xml文件
<context:component-scan base-package="com.aspectj.demo5"/>
<aop:aspectj-autoproxy />
只列举一个,其他都类似
<bean id="someService" class="com.aspectj.demo5.SomeServiceImpl"/>
<bean id="myAspect" class="com.aspectj.demo5.MyAspect"/>
<aop:config>
<aop:pointcut expression="execution(* *..SomeServiceImpl.run(..))" id="afterPointCut"/>
<aop:aspect ref="myAspect">
<aop:after method="afterExecute" pointcut-ref="afterPointCut"/>
aop:aspect>
aop:config>