一、面向切面编程简介:
在调用某些类的方法时,要在方法执行前或后进行预处理或后处理;预处理或后处理的操作被封装在另一个类中。如图中,UserService类在执行addUser()或updateUser方法前开启事务,执行完后要提交事务;而几乎所有数据库操作都是如此,那么就可以将事务操作的方法提取出封装到一个类里。然后再利用代理类进行处理(目标类方法增强),返回代理类对象
二、AOP相关术语
Target:目标类,需要被增强的类。
JoinPoint:连接点,目标类上需要被增强的方法。(这些方法可以被增强,也可能不增强)。
PointCut:切入点,被增强的连接点(已经增强了)。切入点术语特殊的连接点
Advice:增强/通知,增强的方法。
weaving:织入,将切入点和通知结合,生成代理类过程。
Proxy:代理类。
Aspect:切面,切入点和通知结合形成的面
三、JDK动态代理模拟AOP
1、项目结构(接口+目标类+切面类+代理类+测试类)
2、新建接口UserService
package hjp.springAOP.jdkProxy; public interface UserService { void addUser(); void updateUser(); }
3、新建目标类UserServiceImpl,并实现接口UserService
package hjp.springAOP.jdkProxy; public class UserServiceImpl implements UserService { @Override public void addUser() { // TODO Auto-generated method stub System.out.println("jdk add user"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("jdk update user"); } }
4、新建切面类MyAspect
package hjp.springAOP.jdkProxy; /** * 切面类,用于存放增强 * * @author JiaPeng * */ public class MyAspect { public void beafore() { System.out.println("before"); } public void after() { System.out.println("after"); } }
5、新建代理类MyFactory
package hjp.springAOP.jdkProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。 * * @author JiaPeng * */ public class MyFactory { public static UserService createService() { // 创建目标类 final UserService userService = new UserServiceImpl(); // 创建切面类 final MyAspect myAspect = new MyAspect(); // 使用jdk动态代理,生成代理类 // 第一个参数是,当前类下的类加载器,第二个参数是目标类所继承的接口数组,第三个参数是匿名内部类 // 匿名内部类也就是没有名字的内部类;正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写;但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 UserService proxyService = (UserService) Proxy.newProxyInstance(MyFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() { // 代理类每一个方法执行时,都将调用处理类的invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub // 执行前通知 myAspect.beafore(); // 执行目标类的相应方法 Object obj = method.invoke(userService, args); // 执行后通知 myAspect.after(); return obj; } }); return proxyService; } }
6、新建测试类
package hjp.springAOP.jdkProxy; import org.junit.Test; public class TestApp { @Test public void demo1() { UserService userService = MyFactory.createService(); userService.addUser(); userService.updateUser(); } }
四、CGLIB模拟AOP
cglib 字节码增强工具,一般框架都使用。只要有类就可以增强
1、项目结构(cglib的jar包已被spring打包好了,所以添加了spring的主要jar包就可以了)
2、新建目标类UserServiceImpl,没有接口
package hjp.springAOP.cglibProxy; public class UserServiceImpl { public void addUser() { System.out.println("cglib add user"); } public void updateUser() { System.out.println("cglib update user"); } }
3、新建切面类
package hjp.springAOP.cglibProxy; /** * 切面类,用于存放增强 * * @author JiaPeng * */ public class MyAspect { public void beafore() { System.out.println("before"); } public void after() { System.out.println("after"); } }
4、新建代理类
package hjp.springAOP.cglibProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.eclipse.jdt.internal.compiler.classfmt.FieldInfoWithAnnotation; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。 * * @author JiaPeng * */ public class MyFactory { public static UserServiceImpl createService() { // 创建目标类 final UserServiceImpl userServiceImpl = new UserServiceImpl(); // 创建切面类 final MyAspect myAspect = new MyAspect(); // 使用cglib创建代理类,其实现方式就是在cglib运行时,动态创建目标类子类(该子类就是代理类,Java动态代理是基于接口或父类的) // 创建核心类 Enhancer enhancer = new Enhancer(); // 设置父类 enhancer.setSuperclass(userServiceImpl.getClass()); // 代理类方法将调用回调函数,等效JDK InvocationHandler // 接口Callback,子接口MethodInterceptor对方法进行增强 enhancer.setCallback(new MethodInterceptor() { @Override // 前三个参数与jdk动态代理invoke相同 // 第四个参数是方法代理 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // TODO Auto-generated method stub // 切面类的前通知 myAspect.beafore(); // 目标方法 //Object object = method.invoke(userServiceImpl, args); Object object = methodProxy.invokeSuper(proxy, args);//执行代理类(子类)父类方法(父类就是目标类),效果和上面的一样 // 切面类后通知 myAspect.after(); return object; } }); // 创建代理类 return (UserServiceImpl) enhancer.create(); } }
5、新建测试类
package hjp.springAOP.cglibProxy; import org.junit.Test; public class TestApp { @Test public void demo1() { UserServiceImpl userService = MyFactory.createService(); userService.addUser(); userService.updateUser(); } }
原文:http://www.cnblogs.com/hujiapeng/p/4792398.html