AOP
(Aspect Oriented Programming),即面向切面编程
,最主要的思想就是纵向重复,横向抽取。要想实现AOP,其底层实现是使用了动态代理技术
,在Spring中,动态代理技术分为传统的JDK动态代理
和Cglib动态代理
。这两种代理机制区别是:
JDK动态代理:针对实现了接口的类进行代理
Cglib动态代理:针对没有实现接口的类进行代理,底层是字节码增强技术,生成当前类的子类对象。
源码地址:https://github.com/jitwxs/blog_sample
假设我们有一个UserService接口,其中具有CRUD方法:
public interface UserService {
void save();
void delete();
void update();
void query();
}
它有一个实现类,只是简单的输出了信息:
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("save");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void query() {
System.out.println("query");
}
}
如果我们想要对这四个方法进行增强,例如在每个方法开头和结尾开启和提交事务,例如:
public void delete() {
System.out.println("开启事务");
System.out.println("delete");
System.out.println("提交事务");
}
如果不使用AOP思想或动态代理技术,要写很多的冗余代码。
Step1: 要有一个实现InvocationHandler
接口的类,编写MyInvocationHandler
类:
/**
* 基于 JDK 的动态代理
* @author jitwxs
* @since 2018/12/6 15:18
*/
public class MyInvocationHandler implements InvocationHandler {
/**
* 要代理类的对象
*/
private Object targetObj;
/**
* 在创建对象时将要代理类的对象传进来
*/
public MyInvocationHandler(Object targetObj) {
this.targetObj = targetObj;
}
/**
* @param proxy 方法对象(没有实际作用)
* @param method 该方法对象所在的类对象实例
* @param args 方法参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务");
/*
* obj:调用谁的方法用谁的对象
* args 方法调用时的参数
*/
Object invoke = method.invoke(targetObj, args);
System.out.println("提交事务");
return invoke;
}
}
Step2: 编写UserService的动态代理类:
/**
* UserService的动态代理类
* @author jitwxs
* @since 2018/12/6 15:19
*/
public class UserServiceProxy {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
public UserService getUserServiceProxy() {
// 创建实现InvocationHandler类的对象,将要代理类的对象传进去
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
/*
* public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
* loader : 类加载器(指定当前类即可)
* interfaces 要代理的类实现的接口列表
* h:实现具体代理操作的类(要实现InvocationHandler接口)
*/
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceProxy.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
myInvocationHandler);
return userServiceProxy;
}
}
Step3: 编写测试方法
/**
* JDK动态代理测试类
* @author jitwxs
* @since 2018/12/6 15:21
*/
public class JdkProxyTest {
public static void main(String[] args) {
//创建UserService实例
UserService us = new UserServiceImpl();
// 创建UserService代理类实例
UserServiceProxy userServiceProxy = new UserServiceProxy(us);
// 返回代理后增强过的UserService实例
UserService usProxy = userServiceProxy.getUserServiceProxy();
usProxy.delete();
}
}
Step0: 导入 Cglib 依赖包:
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>3.2.4version>
dependency>
Step1: 编写 userService 实现 MethodInterceptor
接口的 Cglib 动态代理类:
/**
* UserService的动态代理类
* @author jitwxs
* @since 2018/12/6 15:22
*/
public class UserServiceProxy2 implements MethodInterceptor {
public UserService getUserServiceProxy() {
// 生成代理对象
Enhancer enhancer = new Enhancer();
// 设置对谁进行代理
enhancer.setSuperclass(UserServiceImpl.class);
// 代理要做什么
enhancer.setCallback(this);
// 创建代理对象
UserService us = (UserService) enhancer.create();
return us;
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("开启事务");
Object invoke = methodProxy.invokeSuper(o, args);
System.out.println("提交事务");
return invoke;
}
}
Step2: 编写测试方法
/**
* Cglib 动态代理测试类
* @author jitwxs
* @since 2018/12/6 15:34
*/
public class CglibProxyTest {
public static void main(String[] args) {
// 创建UserService代理类实例
UserServiceProxy2 userServiceProxy2 = new UserServiceProxy2();
// 返回代理后增强过的UserService实例
UserService usProxy = userServiceProxy2.getUserServiceProxy();
usProxy.query();
usProxy.save();
usProxy.update();
usProxy.delete();
}
}
(1)JDK的动态代理
InvocationHanlder
接口(2)cglib的动态代理
MethodInterceptor
接口