1. 神马是AOP ?
AOP,英文(Aspect Oriented Programming)的缩写,意为:面向切面编程,通过预编译方式和运行时期动态代理实现程序功能的统一维护的一种技术。
AOP可以看做是OOP(面向对象编程)的延续,是软件开发的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从二是的业务各部分之间的 耦合度降低 ,提高程序的 可重用性 ,同时提高了开发的效率。
1.1 AOP的优势与引用
-
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
-
AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
-
经典应用:事务管理、性能监视、安全检查、缓存 、日志等
-
Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
1.2 AOP术语
- target目标类:需要被代理的类。例如:UserService
- JoinPoint(连接点):类里面可以被增强的方法,这些方法称为连接点。例如:所有方法
- PointCut(切入点): 已经被增强的连接点。例如:addUser()
- advice (通知/增强) : 拦截到Joinpoint之后所要做的事情就是通知
- Weaving(织入) :把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
- proxy(代理类): 一个类被AOP织入增强后,就产生一个结果代理类
- Aspect(切面类): 是切入点pointcut和通知advice的结合 ; 一个线是一个特殊的面; 一个切入点和一个通知,组成成一个特殊的面。
过程图如下:
1.3 AOP的实现原理
aop底层采用代理机制进行实现,主要有两种实现方式:
- 接口 + 实现类 :有接口情况,使用 动态代理创建接口实现类 代理对象
- 实现类 :没有接口情况,使用动态代理创建类的子类代理对象
2. 两种实现方式的讲解
2.1 JDK动态代理实现AOP
JDK动态代理 ,可以看做是对“装饰者模式”的简化。使用前提:必须有接口
一般有如下的类来实现:
- 目标类:接口 +实现类
- 切面类:用于存放通知
- 工厂类:用于生产代理
- 测试类:用于测试
2.2 CGLIB字节码增强实现AOP
- 没有接口,只有实现类。
- 采用字节码增强框架cglib(spring 也是采用这个来生成代理对象的),在运行时创建目标类的子类,从而达到对目标类的增强。
- 注意:需要导入相应的jar 包:
- cglib-2.2.jar
- asm-3.3.jar
2.3 实现案例(注意:使用cglib的静态类测试要导包)
UserService,UserServiceImpl(目标类):
public interface UserService {
public void addUser();
public void updataUser();
public void deleteUser();
}
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("添加用户成功");
}
@Override
public void updataUser() {
// TODO Auto-generated method stub
System.out.println("更新用户");
}
@Override
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("删除用户");
}
}
切面类:
public class UserAspect {
public void before() {
// TODO Auto-generated method stub
System.out.println("------------在之前的操作-----------------");
}
public void after() {
// TODO Auto-generated method stub
System.out.println("------------在之后的操作-----------------");
}
}
工厂类和测试类(为了方便,写一块了)
public class UserBeanFactory {
/**
* jdk动态代理实现的增强
*
* @return
*/
public static UserService createServiceByJdkProxy() {
// 1. 目标类
final UserService userService = new UserServiceImpl();
// 2. 切面类
final UserAspect userAspect = new UserAspect();
UserService proxyService = (UserService) Proxy.newProxyInstance(UserBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (methodName.equals("addUser")) {
userAspect.before();
Object object = method.invoke(userService, args);
userAspect.after();
return object;
} else {
return method.invoke(userService, args);
}
}
});
return proxyService;
}
public static UserServiceImpl createServiceByCglib() {
final UserServiceImpl userService = new UserServiceImpl();
final UserAspect userAspect = new UserAspect();
// 采用cglib ,底层创建目标类的子类
Enhancer enhancer = new Enhancer();
// 确定父类
enhancer.setSuperclass(userService.getClass());
/*
* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效 jdk invoke() 参数1、参数2、参数3:以invoke一样 参数4:methodProxy
* 方法的代理
*
*/
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
String methodName = method.getName();
Object object = null;
if (methodName.equals("addUser")) {
userAspect.before();
object = method.invoke(userService, args);
userAspect.after();
// TODO Auto-generated method stub
} else {
// * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
object = methodProxy.invokeSuper(proxy, args);
}
return object;
}
});
// 3.4 创建代理
UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService;
}
public static void main(String[] args) {
// UserService userService = createServiceByJdkProxy();
UserService userService = createServiceByCglib();
userService.addUser();
userService.deleteUser();
}
}