【Java】关于Proxy动态代理的一些笔记

【Java】Proxy动态代理案例

One:一些相关的笔记

1、关于接口的default关键字

java1.8 接口组成更新,接口新增默认方法,关键字“default”,默认方法在接口的实现类中,不强制重写,但是也可以被重写,而且在接口中,默认方法可以有方法体内容。如果实现类没有重新默认方法,但是会继承这个默认方法,所以创建实现类对象后,可以调用默认方法。

注意事项:
1、当一个实现类实现了多个接口,多个接口里都有相同的默认方法时,实现类必须重写该默认方法,否则编译错误。(a.实现类自己重写逻辑。b. 实现类使用super关键字指定使用哪个接口的默认方法)
2、接口静态方法,接口中支持静态方法,将默认方法的关键字换成static即可。
3、继承类可以直接使用接口中的static方法,也可以创建对象后使用接口中的default方法。

2、代理与代理的几种方式

静态代理:提供服务的接口 <= 接口的代理类(增加切面实现功能添加) <= 各类业务功能

动态代理:提供服务的接口 <= 接口实现类(各类业务功能) <= 代理类(内部包含业务切面)

实现代理的几种方式:
1、业务与切面耦合在一起
2、子类代理实现切面功能增强
3、使用静态代理分离业务
4、使用静态代理分离业务和切面(在静态代理的基础上,将业务切面分离到独立的切面接口,然后针对接口实现不同的事务切面,最后在代理中调用事务切面,进而实现分离业务和切面)
5、使用动态代理优化业务和切面的耦合(重点)

3、关于AOP的一些术语

切面:重复的、公共的、通用的功能。
连接点:即目标方法,因为在目标方法中要实现目标方法的功能和切面功能。
切入点:指定切入的位置,多个连接点构成切入点。切入点可以是一个目标方法/一个类的所有方法/某个包下的所有类的方法。
目标对象:被操作的对象。
通知:指定切入的时机,在目标方法执行前还是执行后还是出错时,还是环绕目标方法切入的切面功能。

Two:一个案例

简介:当前有Service接口提供采购服务(buy)与售后服务(afterSales), 现针对Service接口实施动态代理代理,并且在代理的同时通过AOP接口(aopService)增添对采购服务与售后服务的切面事务(before、after、rollback)。具体效果如图所示:
在这里插入图片描述

1、目录结构

在这里插入图片描述

2、案例源码

(1)Service.java
package com.Etui.dynamicProxy;

public interface Service {
    // 购买服务
    void buy();

    // 售后服务
    default String afterSales(Integer id){return "售后服务…………………………" + id ;};
}
(2)BookServiceImpl.java
package com.Etui.dynamicProxy;

public class BookServiceImpl implements Service {
    @Override
    public void buy() {
        System.out.println("图书购买服务………………");
    }

    @Override
    public String afterSales(Integer id) {
        System.out.println("售后服务被调用……………………");
        return "Success";
    }
}
(3)AopService.java
package com.Etui.dynamicProxy.aop;

public interface AopService {
    // 事务开启
    default void before() {}

    // 事务关闭
    default void after() {}

    // 事务回滚
    default void rollback() {}

}
(4)AopServiceImpl.java
package com.Etui.dynamicProxy.aop;

public class AopServiceImpl implements AopService {
    @Override
    public void before() {
        System.out.println("事务开启…………………………");
    }

    @Override
    public void after() {
        System.out.println("事务关闭…………………………");
    }

    @Override
    public void rollback() {
        System.out.println("事务回滚…………………………");
    }
}
(5)ProxyFactory.java
package com.Etui.dynamicProxy;


import com.Etui.dynamicProxy.aop.AopService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory implements InvocationHandler {
    private Object target; // 代理的目标对
    private AopService aop; // 事务切面

    public ProxyFactory(Object target, AopService aop) {
        this.target = target;
        this.aop = aop;
    }

    // 创建代理对象
    public Object createProxy() {
        // 创建代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {

//        System.out.println("所有事务开启前…………………………");
        Object result = null; // 执行目标对象的方法
        try {
            aop.before();
            result = method.invoke(target, args);
            aop.after();
        } catch (Exception e) {
            aop.rollback();
        }
        return result;
    }


(6)测试类(MyTest.java)
package com.Etui.test3;

import com.Etui.dynamicProxy.BookServiceImpl;
import com.Etui.dynamicProxy.ProxyFactory;
import com.Etui.dynamicProxy.Service;
import com.Etui.dynamicProxy.aop.AopService;
import com.Etui.dynamicProxy.aop.AopServiceImpl;
import org.junit.Test;

public class MyTest {

    // 测试动态代理
    @Test
    public void testProxy() {

        // 创建被代理对象
        Service buyBook = new BookServiceImpl();
        // 事务切面
        AopService aop = new AopServiceImpl();

        // 创建代理对象并实现代理
        Service bookProxy = (Service) new ProxyFactory(buyBook, aop).createProxy();

        // 调用被代理对象的方法
        bookProxy.buy();
        System.out.println("--------------+++++++--------------");
        String result = bookProxy.afterSales(001);
        System.out.println("afterSales返回值为:" + result);

    }
}
(7)测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIHiKUcA-1650896736021)(C:\Users\34162\AppData\Roaming\Typora\typora-user-images\image-20220425222146393.png)]

Over!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值