一、概念?
AOP是Aspect Oriented Programming的缩写,意思为面向切面编程。它最大的作用,那就是为了解决程序功能扩展的问题,而且在增强 期间不需要改动原代码。底层运用动态代理模式实现。
动态代理的实现有两种,而核心其实就是多态。无论是基于JDK的动态代理还是基于cglib的动态代理,只不过一个是利用接口和实现类的关系,一个是利用父类和子类的关系。
- 基于JDK的动态代理
这种动态代理应用的特点为:如果哪一个真实类有实现接口,那么就采用这种方式,创建出来接口的另一个实现类作为代理类。它是利用接口和实现类的关系,建立一个实现共同接口的代理类。
- 基于cglib的动态代理:如果真实类是一个普通类,没有实现接口,那么就采用这种方式, 创建出来真实类的子类作为代理类。
通过例子来体会
@Test //基于JDK代理 public void fun01() { //创建真实对象 final UserService userService = new UserServiceImp(); //获取真实对象的加载器、接口,创建一个代理类 //反射调用方法 UserService proxyInstance = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* * proxy : 代理对象,几乎不用 * method: 方法的引用 save() --- save方法的引用 * args: 方法参数 */ if ("saveUser".equals(method.getName())) { Logger.logger(); } ////反射调用 把结果跑出去,让代理对象也能收到结果。 return method.invoke(userService, args); // return null; } }); //代理并不会干活,真正干活的是真实类 proxyInstance.saveUser(); }
@Test //基于Cglib动态代理 //如果真实类是一个普通类,没有实现接口,那么就采用这种方式, 创建出来真实类的子类作为代理类。 public void fun02() { //启用创建执行者 Enhancer enhancer = new Enhancer(); //创建真实对象 final UserService2 userService = new UserService2(); enhancer.setSuperclass(UserService2.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Logger.logger(); return method.invoke(userService, objects); } }); UserService2 proxyInstance = (UserService2) enhancer.create(); proxyInstance.test(); }
二、AOP术语
三、AOP入门
- 定义业务逻辑类
public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("调用了UserServiceImpl 的 save方法"); } }
- 定义增强类
public class Logger { public static void log(){ System.out.println("输出日志了~~"); } }
- 导入jar包
a. 导入 spring必须的jar b. 额外导入: spring-aop-xx.jar,spring-aspect-xx.jar 面向切面过程中,Spring AOP是遵循了AOP联盟的规范实现的,所以需要有AOP联盟的接口包 aopalliance-x.x.jar,接口包依赖aspectjweaver-x.x.x.jar
- xml配置
<?xml version="1.0" encoding="UTF-8"?> <!--aop入门配置--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="gaga"/> <bean id="us" class="gaga.service.serviceimp.UserServiceImp"/> <bean id="ul" class="gaga.utils.Logger"/> <aop:config> <aop:pointcut id="a" expression="execution(* gaga.service.serviceimp.*.*(..))"/> <aop:aspect ref="ul"> <aop:after method="logger" pointcut-ref="a"/> </aop:aspect> </aop:config> </beans>