利用转账演示事务控制
image.png

动态代理:

image.png

特点:字节码随用随创建,随用岁加载
作用:不修改源码的基础上对方法增强
分类:
基于接口的动态代理
基于子类的动态代理

基于接口的动态代理:

涉及的类:Proxy
提供者:JDK官方
如何创建代理对象:
使用Proxy类中的newProxyInstance方法
创建代理对象的要求:
被代理类最少实现一个接口,如果没有则不能使用

newProxyInstance方法的参数:
ClassLoader:类加载器
它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
Class[]:字节码数组
它是用于让代理对象和被代理对象有相同方法。固定写法。
InvocationHandler:用于提供增强的代码
它是让我们写如何代理。一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
此接口的实现都是谁用谁写。

  1. public static void main(String[] args) {
  2. final Producer producer = new Producer();
  3. /**
  4. * 动态代理
  5. */
  6. producer.saleProduct(113f);
  7. Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {
  8. /**
  9. * 作用:执行被代理对象的任何接口方法都会经过该方法
  10. * @param proxy 代理对象的引用
  11. * @param method 当前执行的方法
  12. * @param args 当前执行方法所需的参数
  13. * @return 和被代理对象方法有相同的返回值
  14. * @throws Throwable
  15. */
  16. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  17. return null;
  18. }
  19. });
  20. }

基于子类的动态代理

  1. <dependency>
  2. <groupId>cglib</groupId>
  3. <artifactId>cglib</artifactId>
  4. <version>2.1_3</version>
  5. </dependency>

涉及的类:Enhancer
提供者:cglib
如何创建代理对象:
使用Enhancer类中的create方法
创建代理对象的要求:
被代理类不能是最终类

create方法的参数:
class:字节码
它是用于指定被代理对象的字节码。
callback:用于提供增强的代码

它是让我们写如何代理。一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
此接口的实现都是谁用谁写。
一般写的都是该接口的子接口实现类:MethodInterceptor

  1. public static void main(String[] args) {
  2. final Producer producer = new Producer();
  3. Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
  4. /**
  5. * @param proxy 代理对象的引用
  6. * @param method 当前执行的方法
  7. * @param args 当前执行方法所需的参数
  8. * @param methodProxy 当前执行方法的代理对象
  9. * @return
  10. * @throws Throwable
  11. */
  12. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  13. Object returnValue = null;
  14. //获取方法执行的参数
  15. Float money = (Float) args[0];
  16. // 判断当前方法是不是销售
  17. if ("saleProduct".equals(method.getName())) {
  18. returnValue = method.invoke(producer, money * 0.8f);
  19. }
  20. return returnValue;}
  21. });
  22. cglibProducer.saleProduct(12000f);
  23. }
  24. }