? AOP ( Aspect-Oriented Programming )即面向切面编程,它与OOP (Object-Oriented Programming , 面向对象编程) 相辅相成,提供了与OOP 不同的抽象软件结构的视角。在OOP 中,以类作为程序的基本单元,而AOP 中的基本单元是Aspect (切面)。Struts2的拦截器设计就是基于AOP 的思想,是个比较经典的应用。
? 在Java中有多种动态代理技术,例如JDK、CGLIB、Javassist、ASM,其中最常用的动态代理技术是JDK和CGLIB。目前,在Spring AOP中常用JDK和CGLIB两种动态代理技术。
? JDK 动态代理是java.lang . reflect. *包提供的方式,它必须借助一个接口才能产生代理对象。因此,对于使用业务接口的类, Spring 默认使用JDK 动态代理实现AOP 。
实例演示:
创建应用,创建接口及实现类,在src的目录下创建一个dynamic.jdk包,在该包中创建接口TestDao和接口实现类TestDaoImpl。该实现类作为目标类,在代理类中对其方法进行增强处理。
TestDao的代码如下:
package dynamic.jdk;
public interface TestDao {
public void save();
public void modify();
public void delete();
}
TestDaoImpl的代码如下:
package dynamic.jdk;
public class TestDaoImpl implements TestDao {
@Override
public void save() {
System.out.println("保存");
}
@Override
public void modify() {
System.out.println("修改");
}
@Override
public void delete() {
System.out.println("删除");
}
}
创建切面类
在src目录下创建一个aspect包,在该包下创建切面类MyAspect,注意在该类中可以定义多个通知(增强处理的功能方法)。
MyAspect的代码如下:
package aspect;
/**
* 切面类,可以定义多个通知,即增强处理的方法
*/
public class MyAspect {
public void check() {
System.out.println("模拟权限控制");
}
public void except() {
System.out.println("模拟一场处理");
}
public void log() {
System.out.println("模拟日志记录");
}
public void monitor() {
System.out.println("性能检测");
}
}
创建代理类
在dynamic.jdk包中创建代理类JDKDynamicProxy。在JDK动态代理中代理类必须实现java.lang.reflect.InvocationHandler接口,并编写代理方法,在代理方法中需要通过Proxy实现动态代理。
JDKDynamicProxy的代码如下:
package dynamic.jdk;
import aspect.MyAspect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKDynamicProxy implements InvocationHandler {
// 声明目标类接口对象(真实对象)
private TestDao testDao;
// 创建代理的方法,建立代理对象和真实对象的代理关系,并返回代理对象
public Object createProxy(TestDao testDao) {
this.testDao = testDao;
// 1. 类加载器
ClassLoader cld = JDKDynamicProxy.class.getClassLoader();
// 2. 被代理对象实现的所有接口
Class[] clazz = testDao.getClass().getInterfaces();
// 3. 使用代理类进行增强,返回代理后的对象
return Proxy.newProxyInstance(cld, clazz, this);
}
/**
* 代理的逻辑方法,所有动态代理类的方法调用都交给该方法处理
* proxy是被代理对象
* method是将要被执行的方法
* args是执行方法时需要的参数
* return指返回代理结果
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 创建一个切面
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.check();
myAspect.except();
// 在目标类上调用方法标并传入参数,相当于调用testDao中的方法
Object obj = method.invoke(testDao, args);
// 后增强
myAspect.log();
myAspect.monitor();
return obj;
}
}
创建测试类
在dynamic.jdk包中创建测试类JDKDynamicTest。在主方法中创建代理对象和目标对象,然后从代理对象中获取对目标对象增强后的对象,最后调用该对象的添加、修改和删除方法。
JDKDynamicTest的代码如下:
package dynamic.jdk;
public class JDKDynamicTest {
public static void main(String[] args) {
// 创建代理对象
JDKDynamicProxy jdkProxy = new JDKDynamicProxy();
// 创建目标对象
TestDao testDao = new TestDaoImpl();
// 从代理对象中获取增强后的目标对象,该对象是一个被代理的对象,它会进入代理的逻辑方法invoke中
TestDao testDaoAdvice = (TestDao) jdkProxy.createProxy(testDao);
// 执行方法
testDaoAdvice.save();
System.out.println("===============");
testDaoAdvice.modify();
System.out.println("===============");
testDaoAdvice.delete();
}
}
运行效果:
? JDK 动态代理必须提供接口才能使用,对于没有提供接口的类,只能采用CGLIB 动态代理。
? CGLIB (Code Generation Library ) 是一个高性能开源的代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring Core 包中己经集成了CGLIB 所需要的JAR 包,不需要另外导入JAR 包。
实例演示:
创建目标类
在src目录下创建一个dynamic.cglib包,在该包中创建目标类TestDao,注意该类不需要实现任何接口。
TestDao的代码如下:
? 在Spring中默认使用JDK动态代理实现AOP编程。使用org.springframework.aop.framwork.ProxyFactoryBean创建代理是Spring AOP实现的最基本方式。
根据Spring中通知在目标类方法中的连接点位置,通知可以分为6种类型。
? 环绕通知(org.aopallicance.intercept.MethodIntercerptor)是在目标方法执行前和执行后实施增强,可应用于日志记录、事务处理等功能。
? 前置通知(org.springframework.aop.MethodBeforeAdvice)实在目标方法执行前实施增强,可应用于权限管理等功能。
? 后置返回通知(org.springframework.aop.AfterReturningAdvice)是在目标方法成功执行后实施增强,可应用于关闭流、删除临时文件等功能。
? 后置通知(org.springframework.aop.AfterAdvice)是在目标方法执行后实施增强,与后置返回通知不同的是,不管是否发生异常都要执行该类通知,该类通知可应用于释放资源。
? 引入通知(org.springframework.aop.IntroductionInterceptor)是在目标类中添加一些新的方法和属性,可应用于修改目标类(增强类)。
? ProxyFactoryBean是org.springframework.beans.factory.FactoryBean接口的实现类,FactoryBean负责实例化一个Bean实例,ProxyFactoryBean负责为其他Bean实例创建代理实例。
*** ProxyFactoryBean类的常用属性**:
? AspectJ是一个基于Java语言的AOP框架。使用AspectJ实现Spring AOP的方式有两种,一是基于XML配置开发AspectJ,二是基于注解开发AspectJ。
? 基于XML配置开发AspectJ是指通过XML配置文件定义切面、切入点及通知,所有这些定义都必须在<aop:config>
元素内。<aop:config>
元素及其子元素如下表所示:
? 各类型通知与目标方法的执行过程,具体过程如图所示:
? 基于注解开发AspectJ要比基于XML配置开发AspectJ便捷许多,所以在实际开发中推荐使用注解方法。
? AspectJ注解,如下表所示:
原文:https://www.cnblogs.com/yihangjou/p/12005497.html