AOP的全称是面向方面编程,即面向方面编程。它是面向对象编程(OOP)的补充。目前已经成为一种比较成熟的编程方式。
在传统的业务处理代码中,通常会进行事务、日志等操作。虽然使用OOP可以通过组合或者继承来实现代码复用,但是如果要实现一个功能(比如日志),同样的代码还是会分散在各种方法中。这样,如果你想关闭一个功能或者修改它,你必须修改所有相关的方法。这不仅增加了开发者的工作量,也提高了代码的错误率。
为了解决这个问题,AOP的想法应运而生。AOP采用横向抽取机制,将分散在各种方法中的重复代码抽取出来,然后在程序编译或运行时将抽取出来的代码应用到需要执行的地方。采用横向抽取机制和传统的OOP思想显然是不可能的,因为OOP只能实现父子关系的纵向复用。虽然 AOP 是一种新的编程思想,但它并不能替代 OOP。它只是OOP的扩展和补充。
AOP 在编写业务逻辑时,开发人员可以专注于核心业务,而不必过多关注其他业务逻辑的实现,不仅提高了开发效率,还增强了代码的可维护性。
目前最流行的AOP框架有两种:spring AOP和AspectJ。Spring AOP 是用纯 Java 实现的,没有特殊的编译过程和类加载器。增强代码在运行时通过代理编织到目标类中。AspectJ 是一个基于 Java 语言的 AOP 框架,从 spring 2.0 开始,spring AOP 引入了对 AspectJ 的支持,它扩展了 Java 语言,并提供了一个特殊的编译器,在编译时提供横向代码编织。
Aspect:在实际应用中,Aspect通常是指用于横向插入系统功能(如事务、日志等)的封装类。要被Spring容器识别为切面,需要通过配置文件中的元素来指定。
Joinpoint:在程序执行过程中的某个阶段,实际上是对一个对象的操作,比如方法调用或者异常抛出。在 Spring AOP 中,连接点是一个方法调用。
切入点:指切面与程序流的交集,即需要处理的连接点。通常在程序中,切入点是指类或方法名。如果要对所有以 add 开头的方法应用通知,则所有符合该规则的方法都是切入点。
Advice:AOP框架在特定切入点处进行的增强处理,即在定义的切入点处要执行的程序代码。可以理解为切面类中的方法,是切面的具体实现。
目标对象:指所有被通知的对象,也称为增强对象。如果AOP框架采用动态AOP实现,那么对象就是代理对象。
代理:通知应用到目标对象后动态创建的对象。
编织:将切片代码插入目标对象以生成代理对象的过程。
1.创建web工程,将Spring框架需要的JAR包导入到工程lib目录下,发布到类路径下。
2.在src目录下,创建一个包(比如我创建的yjf.jdk),在包下创建接口UserDao.java
包yjf.jdk;
公共接口 UserDao {
公共无效添加用户();
公共无效删除用户();
}
3.在yjf.jdk包中,创建UserDao接口实现的类UserDaoImpl.java,分别实现接口中的方法
包yjf.jdk;
公共类 UserDaoImpl 实现 UserDao {
公共无效添加用户(){
System.out.println("添加用户");
}
公共无效删除用户(){
System.out.println("删除用户");
}
}
4.在src目录下再创建一个包(比如我创建的yjf.aspect包),在包下创建切面类MyAspect.java。在这个类中,定义一个检查模拟权限的方法和一个模拟日志记录的方法。这两个方法是方面的通知
包yjf.aspect;
公共类 MyAspect {
公共无效 check_Permissions(){
System.out.println("模拟检查权限......");
}
公共无效日志(){
System.out.println("模拟日志......");
}
}
5.在yjf.jdk包下,创建Proxy类JdkProxy,需要实现InvocationHandler接口,编写Proxy方法。在Proxy方法中,需要通过Proxy类实现动态Proxy
包yjf.jdk;
导入 java.lang.reflect.InvocationHandler;
导入java.lang.reflect.Method;
导入 java.lang.reflect.Proxy;
导入 yjf.aspect.*;
/* JDK 代理类 */
公共类 JdkProxy 实现 InvocationHandler {
//声明目标类接口
私人用户道用户道;
//创建代理方法
公共对象 createProxy(UserDao userDao){
this.userDao = userDao;
//1. 类加载器
类加载器 classLoader = JdkProxy.class.getClassLoader();
//2。代理对象实现的所有接口
类[] clazz = userDao.getClass().getInterfaces();
//3. 使用代理类增强代理后返回对象
return Proxy.newProxyInstance(classLoader, clazz, this);
}
/*
* 动态代理类的所有方法调用都由invoke()方法处理
* 被表示后的代理对象
* method 要执行的方法信息(反射)
* asgs 执行方法所需的参数
*
* */
@覆盖
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
//声明部分
MyAspect myAspect = new MyAspect();
//预增强
myAspect.check_Permissions();
//调用目标类上的方法并传入参数
对象 obj = method.invoke(userDao, args);
//侯增强
myAspect.log();
返回对象;
}
}
6.在yjf.jdk包中,创建测试类JdkTest,在该类中创建代理对象和目标对象,然后从代理对象中获取目标对象userDao增强的对象,最后调用add和delete方法在对象中。
包yjf.jdk;
公共类 JdkTest {
公共静态无效主要(字符串[]参数){
//创建代理对象
JdkProxy jdkProxy = new JdkProxy();
//创建目标对象
UserDao userDao = new UserDaoImpl();
//从代理对象中获取增强的目标对象
UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
//执行方法
userDao1.addUser();
userDao1.deleteUser();
}
}
运行结果为:
模拟检查权限......
添加用户
模拟日志……
模拟检查权限......
删除用户
模拟日志……
可以看到userDao实例中添加和删除用户的方法已经成功调用,调用前后增加了查看权限和记录权限的功能。这是 Spring动态代理。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习