一、AOP基本情况
AOP 为Aspect Oriented Programming的缩写,面向切面编程,通过预编译方式和运行期动态代理实现程序的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架的一个重要内容,是函数编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提供程序的可重用性,同时提高的开发的效率。
AOP 采用横向抽取机制,取代了传统的纵向继承体系重复代码。
经典应用:事物管理、性能监视、安全检查、缓存、日志等。
SpringAOP 使用纯JAVA实现,不需要专门的编译过程和类加载器,在运行期通过代理的方式向目标类织入增强代码。
AspectJ是一个基于JAVA语音的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了JAVA语音,提供了一个专门的编辑器,在编译时提供横向代码的织入。
二 AOP的实现原理
aop底层将采用代理机制进行实现。
1、接口+实现类:spring 采用JDK的动态代理Proxy
2实现类:spring采用 cglib 字节码增强。
AOP原理之一DK的动态代理Proxy
其是对装饰者设计模式的简化 使用前提是必须有接口
1目标类:接口+实现类
//接口
public interface IUserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
//实现类
public class UseServiceImpl implements IUserService {
public void addUser() {
System.out.println(“增加用户的方法”);
}
public void updateUser() {
System.out.println(“更改用户的方法”);
}
public void deleteUser() {
System.out.println(“删除用户的方法”);
}
}
2 切面类:y用于存放通知的advice
public class MyAspect {
public void before(){
System.out.println(“advice前置通知”);
}
public void after(){
System.out.println(“advice后置通知”);
}
}
3 代理类:由工厂生成 工厂类编写工厂类
public class MyBeanFactory {
/**
* @return
*/
public static IUserService createUserviceImpl(){
//目标类target
final IUserService userService =new UseServiceImpl();
//切面类 aspect里面还有advice通知
final MyAspect myAspect = new MyAspect();
/**
* 代理类将 目标类(切入点)和切面类(通知ADVICE)结合》》切面
* 代理类Proxy.newProxyInstance(loader, interfaces, h);
* 参数1: loader 类加载器,动态代理运行时创建,任何类都需要类加载器将其加载到内存中
* 参数2:interfaces Class[] interfaces 代理类需要实现的所有接口
* 方式1: 目标类实例.getClass.getInterfaces();注意只能获得自己接口,不能获得父元素接口
* 方式二:new Class[]{UserService.class}
* 例如:Jdbc 驱动–>DriverManager 获得接口的Connection
* 参数3: InyocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部类
* 提供Invoke方法,代理类的每一个方法执行时,都将调用一次invoke
* 参数31 :Object proxy :代理对象
* 参数32: Method method:代理对象当前执行的方法的描述对象(反射)
* 执行方法名: method.getName()
* 执行方法:method.invoke(对象,实际参数)
* 参数33: Object[] args: 方法实际参数
*/
IUserService proxyUserService = (IUserService) Proxy.newProxyInstance(MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
//匿名内部类
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//执行前置方法
myAspect.before();
// 执行目标方法 jionpoint连接点 pointcut 切入点
Object object= method.invoke(userService, args);
//执行后置方法
myAspect.after();
return object;
}
});
return proxyUserService;
}
}
AOP原理之一cglib 字节码增强
不要使用接口了。
1、不需要接口,只有实现类
2、采用字节码增强框架cglib 在运行时创建目标类的子类,从而对目标类进行增强。
导入JAR包
核心为cglib/cglib-2.2.jar
依赖为asm-3.3.jar
这些包spring-core.jar已经包含了。
public class MyBeanFactoryCglib {
/**
* cglib字节码增强
* crtl+shift +o导包
* crtl+T查看子类
* @return
*/
public static UseServiceImpl createUserviceImpl(){
//目标类target
final UseServiceImpl userServiceImpl =new UseServiceImpl();
//切面类 aspect里面还有advice通知
final MyAspect myAspect = new MyAspect();
//3 代理类 ,采用cglib,底层创建目标的子类
//3.1核心类
Enhancer enhancer = new Enhancer();
//3.2确定父类 父类就是要被代理的类。
enhancer.setSuperclass(userServiceImpl.getClass());
/*
* 3.3设置回调函数,MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效JDK invoke()
* 参数1 参数2、参数3 以invoke 一样
* 参数4:methodProxy 方法的代理
*
*/
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//前
myAspect.before();
//执行目标类的方法 第一种方法
Object obj = method.invoke(userServiceImpl, args);
//执行代理类的父类,执行目标类(目标类和代理类 父子关系)第二种方法
methodProxy.invokeSuper(proxy, args);
//后
myAspect.after();
return obj;
}
});
//3.4创建代理
UseServiceImpl proxService = (UseServiceImpl) enhancer.create();
return proxService;
}
}