1. 介绍
AOP就是面向切面编程,简单说就是,在你执行别人的代码中坚插入你想执行的代码,在日常生活中,代理(中介)就是这么一个角色,先看看生活的例子,
在没有代理之前:你现在需要去澳洲旅行,所以你需要买机票,但你不知道那个航空公司比较便宜,甚至那天买会比较便宜,如果你每天都上网查询机票价格,你会觉得很浪费时间,这个时候,你就需要一个代理,帮你完成看机票这么繁琐的事情
有了代理之后:你只需要关注,买完机票之后所做的事情,例如订酒店。买机票这个动作你就交给你的代理去完成就好了
根据上面的这个例子,我们这里就可以看看代码的实现了,我们会分3个方式来看
- 原始JDK实现
- gclib实现
- spring实现
- 半自动
- 全自动
2.最原始的JDK做法
在这个列子中,就是不适用spring实现,这个是一个工厂类,使用者只需要执行这个createUserService的方法,就可以获取UserService的接口,然后执行所需要要的业务
工厂类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanFacotry { public static UserService createUserService() { /** * 1. 创建目标对象 */ final UserService userService = new UserServiceImpl(); /** * 2. 创建切面对象 */ final MyAspect myAspect = new MyAspect(); /** * 3. 整合目标对象 和 切面对象 * 所以需要使用JDK的动态代理,创建代理对象 */ UserService proxyUserService = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),UserServiceImpl.class.getInterfaces(),new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //执行切面的before方法 myAspect.beforeInvokeTarget(); Object obj = method.invoke(userService, args); //执行切面的after方法 myAspect.afterInvokeTarget(); return obj; } }); return proxyUserService; } }
测试类
import org.junit.Test; public class TestAOP { @Test public void test() { UserService userService = MyBeanFacotry.createUserService(); userService.addUser(); } }
3. 通过cgLib实现
这里需要引用cglib的Jar包,但是spring-core的jar包里面已经引用了,所以这里就不需要引入了,测试类跟2的一样就可以,只需要改动一个工厂类就行
public class MyBeanFacotry {public static UserService createUserService() { /** * 1. 创建目标对象 */ final UserService userService = new UserServiceImpl(); /** * 2. 创建切面对象 */ final MyAspect myAspect = new MyAspect(); /** * 3. 整合目标对象 和 切面对象 * 这里使用cglib创建代理对象 */ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { Object obj = arg1.invoke(userService, arg2); return obj; } }); UserService proxyUserService = (UserService)enhancer.create(); return proxyUserService; } }
4. 接下来就是用apache的AOP
跟上面两个方法不同是,这里只需要配置xml,这里需要使用到aopalliance-x.x.jar包和aspectjweaver-x.x.x.jar
接口和实现类跟上面一样,这里就不重复写了,这里只写2个类和一个配置文件
切面类
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class MyAspect implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("切入前"); Object obj = invocation.proceed(); System.out.println("切入后"); return obj; } }
配置文件
稍微讲解一下aop:config节点
其中pointcut 是切入点,expression是表达式,id是切入点ID,主要通知引用
advisor是通知,advice-ref就是指向切面类的bean,pointcut-ref就指向切入点的id
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <bean id="userService" class="com.test.spring.aop.b.UserServiceImpl"></bean> <bean id="myAspect" class="com.test.spring.aop.b.MyAspect"></bean> <aop:config> <aop:pointcut expression="execution(* com.test.spring.aop.b.UserServiceImpl.deleteUser(..))" id="myCutPoint"/> <aop:advisor advice-ref="myAspect" pointcut-ref="myCutPoint"/> </aop:config> </beans>
测试类
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringAOPTest { @Test public void test() { String configPath = new String("com/test/spring/aop/b/springConfig.xml"); ApplicationContext context = new ClassPathXmlApplicationContext(configPath); UserService userService = context.getBean("userService",UserService.class); userService.addUser(); } }
总结,后面的章节将会讲解一下AspectJ