什么是AOP?
AOP(Aspect Oriented Programming),面向切面编程,AOP不是单独指某一种技术,而是一种编程思想,AOP是OOP的一种补充,用于处理各个业务逻辑中的横切关注点,比如日志记录,事务处理,性能统计,异常处理等等。
AOP的主要功能是将大量的通用行为从业务逻辑中抽取出来,将这些行为封装成独立的非业务方法,用于横向切入,这些行为不会对已有的业务逻辑产生任何影响。
AOP是一种设计思想,而Spring AOP则是符合AOP思想的一种框架实现。
Spring AOP
Spring AOP主要有两种实现,分别的JDK动态代理和Cglib动态代理。
JDK动态代理
JDK动态代理是JDK内置的一种动态代理模式,使用反射来接受被代理的类,但是被代理的类必须实现一个接口。
Cglib动态代理
Cglib是一个代码生成的类库,可以在运行时动态生成某个类的子类,所以如果需要被Cglib动态代理,那么就需要被代理类不能被final修饰。
- 在Spring AOP中,如果一个类实现了接口,那么就使用JDK动态代理的方式进行AOP实现,而如果这个类没有实现接口,则使用Cglib动态代理的方式进行AOP实现。如果一个类既没有接口,同时又被final修饰,那么这个类不能进行AOP动态代理。
JDK动态代理
JDK动态代理,由于是JDK内置的代理模式,所以我们不需要引入任何依赖,可以直接使用。
1、编写JDK动态代理代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class JDKProxy implements InvocationHandler {
private Object target;
public JDKProxy(Object target){ this.target = target; }
public Object createProxy() { Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); return proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK动态代理前置通知......"); Object object = method.invoke(target, args); System.out.println("JDK动态代理后置通知......"); return object; } }
|
2、编写一个接口
1 2 3 4 5 6
| public interface UserDao { void save(); void update(); void find(); void delete(); }
|
3、编写被代理类实现该接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("保存用户......"); } @Override public void update() { System.out.println("修改用户......"); } @Override public void find() { System.out.println("查找用户......"); } @Override public void delete() { System.out.println("删除用户......"); } }
|
4、测试
1 2 3 4 5 6 7 8 9 10
| public class JDKProxyTest { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); UserDao proxy = (UserDao) new JDKProxy(userDao).createProxy(); proxy.save(); proxy.update(); proxy.find(); proxy.delete(); } }
|
5、测试结果
1 2 3 4 5 6 7 8 9 10 11 12
| JDK动态代理前置通知...... 保存用户...... JDK动态代理后置通知...... JDK动态代理前置通知...... 修改用户...... JDK动态代理后置通知...... JDK动态代理前置通知...... 查找用户...... JDK动态代理后置通知...... JDK动态代理前置通知...... 删除用户...... JDK动态代理后置通知......
|
Cglib动态代理
Cglib动态代理,需要引入外部依赖,我们可以直接引入Spring的核心依赖即可,Spring中有Cglib的类库。
1、引入依赖
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.8.RELEASE</version> </dependency> </dependencies>
|
2、编写Cglib动态代理代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target){ this.target = target; }
public Object createProxy() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); Object proxy = enhancer.create(); return proxy; }
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("Cglib动态代理前置通知......"); Object object = method.invoke(target, args); System.out.println("Cglib动态代理后置通知......"); return object; } }
|
3、编写被代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class CustomerDao { public void save() { System.out.println("保存客户......"); } public void update() { System.out.println("修改客户......"); } public void find() { System.out.println("查找客户......"); } public void delete() { System.out.println("删除客户......"); } }
|
4、测试
1 2 3 4 5 6 7 8 9 10
| public class CglibProxyTest { public static void main(String[] args) { CustomerDao customerDao = new CustomerDao(); CustomerDao proxy = (CustomerDao) new CglibProxy(customerDao).createProxy(); proxy.save(); proxy.update(); proxy.find(); proxy.delete(); } }
|
5、测试结果
1 2 3 4 5 6 7 8 9 10 11 12
| Cglib动态代理前置通知...... 保存客户...... Cglib动态代理后置通知...... Cglib动态代理前置通知...... 修改客户...... Cglib动态代理后置通知...... Cglib动态代理前置通知...... 查找客户...... Cglib动态代理后置通知...... Cglib动态代理前置通知...... 删除客户...... Cglib动态代理后置通知......
|