AOP
- AOP的概念
- AOP (底层原理)
- AOP 底层使用动态代理
- AOP ( JDK 动态代理)
首先我们来看一下 Spring 的百度百科
Spring 框架是一个开放源代码的J2EE
应用程序框架,由Rod Johnson
发起,是针对 Bean 的生命周期进行管理的轻量级容器( lightweight container )。 Spring 解决了开发者在 J2EE 开发中遇到的许多常见的问题,提供了功能强大的 IOC 、 AOP 及 Web MVC 等功能。 Spring可以单独应用于构筑应用程序,也可以和 Struts 、 Webwork 、 Tapestry 等众多 Web 框架组合使用,并且可以与 Swing 等桌面应用程序 AP 组合。因此, Spring 不仅仅能应用于 J2EE 应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。 Spring 框架主要由七部分组成,分别是 Spring Core , Spring ORM , Spring DAO , Spring Context , Spring Web 和 Spring Web MVC 。
- 所以我们接下来要讲的就是 AOP 的概念。
AOP的概念
同样的,我们先查一下百度百科
在软件行业, AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程
,通过预编译
方式和运行期间动态代理的实现程序功能的统一维护的一种技术。 AOP 是 OOP 的延续,是软件开发中的一个特点,也是 Spring 框架中的一个重要内容,是函数式编程
的一种衍生泛型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度
降低,提高程序的可重用性,同时提高了开发的效率。
- 主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
- 什么是 AOP ?
(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度
降低,提高程序的可重用性,同时提高了开发的效率。
拿我们的登录过程来举例
在登录功能基础之上添加功能
- 权限判断
原始方式:修改源代码进行实现(
if 管理员 *** else if 普通用户
)AOP:不通过修改源代码的方式添加新的功能(增加权限判断模块到判断到主页面之间)
(2)通俗描述:不通过修改源代码的方式,在主干功能里面添加新功能
AOP (底层原理)
AOP 底层使用动态代理
- 第一种 有接口的情况,使用 JDK 的动态代理
动态代理有接口
interface UserDao {
public void login();
}
class UserDaoImpl implements UserDao {
public void login () {
// 登录过程的实现过程
}
}
JDK 动态代理
创建 UserDao 接口实现类代理对象(创建一个代理对象)
- 第二种 没有接口的情况,使用 CGLIB 动态代理
动态代理没有接口的情况
class User {
public void add ()
}
// 子类
class.Person extends User {
public void add () {
supper.add();
// 增强逻辑
}
}
_ CGLIB 动态代理_
创建当前子类中的代理对象,增强类的方法
AOP ( JDK 动态代理)
- 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
java.lang.reflect
Class Proxy
java.lang.Object
java.lang.reflect.Proxy
(1)调用 newProxyInstance 方法
static Object
newProxyInstance(ClassLoader loader,类<?>[] interfaces,InvocationHandler h)
//返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序
方法里面有3个参数
第一个参数,类加载器
第二个参数,增强方法所在的类,这个实现类的接口,支持多个接口
第三个参数,实现里面的接口 InvocationHandler , 创建代理对象,写增强方法
- JDK 动态代理代码
(1)创建接口,定义方法
package com.fairykunkun.dao;
public interface UserDao {
public String update ( String id );
public int add ( int a , int b );
}
(2)创建接口的实现类
package com.fairykunkun.dao;
public class UserDaoImpl implements UserDao {
@Override
public String update ( String id ) {
System.out.println ( "update()方法执行了" );
return id;
}
@Override
public int add ( int a , int b ) {
System.out.println ( "add方法执行了" );
return a + b;
}
}
(3)使用 Proxy 类创建接口的代理对象
package com.fairykunkun.proxy;
import com.fairykunkun.dao.UserDao;
import com.fairykunkun.dao.UserDaoImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main ( String[] args ) {
// 创建接口实现类的代理对象
Class[] interfaces = { UserDao.class };
// Proxy.newProxyInstance ( JDKProxy.class.getClassLoader ( ) , interfaces , new InvocationHandler ( ) {
// @Override
// public Object invoke ( Object proxy , Method method , Object[] args ) throws Throwable {
// return null;
// }
// } );
UserDaoImpl userDao = new UserDaoImpl ( );
UserDao dao = ( UserDao ) Proxy.newProxyInstance ( JDKProxy.class.getClassLoader ( ) , interfaces , new UserDaoProxy ( userDao ) );
int result = dao.add ( 1 , 2 );
System.out.println ( "result:" + result );
}
}
// 创建代理对象的代码
class UserDaoProxy implements InvocationHandler {
// 把创建的是谁的代理对象,把谁传递过来
// 有参数构造传递
public Object object;
public UserDaoProxy ( Object o ) {
this.object = o;
}
// 增强的逻辑
@Override
public Object invoke ( Object proxy , Method method , Object[] args ) throws Throwable {
// 方法之前
System.out.println ( "方法之前执行..." + method.getName ( ) + ":传递的参数..." + Arrays.toString ( args ) );
// 被增强的方法执行
Object res = method.invoke ( object , args );
// 方法之后
System.out.println ( "方法之后执行..." + res );
return res;
}
}
- 测试