使用JDK中的Proxy技术实现AOP功能

AOP技术在企业开发中或多或少都会用到,但用的最多的大概就是做权限系统时,在做权限系统时,我们可能需要粗粒度的权限控制和细粒度的权限控制,对于细粒度的权限控制,我们主要是对方法进行拦截,对方法进行拦截之后,判断用户是否是有权限,有权限就执行该方法,没有权限就不能执行该方法。
现在我们借助一个例子来说明怎么使用JDK中的Proxy技术来实现AOP功能,并且不借助任何其他的框架。
首先新建一个普通的Java Project,名称为AOP。接着在src目录下新建一个it.cast.service包,并在该包下创建PersonService接口,其代码为:

public interface PersonService {
    public void save(String name);
    public void update(String name, Integer personid);
    public String getPersonName(Integer personid);
}

紧接着在src目录下新建一个it.cast.service.impl包,并在该包下创建PersonService接口的实现类——PersonServiceBean.java,其代码为:

public class PersonServiceBean implements PersonService {
    private String user = null;

    public String getUser() {
        return user;
    }

    public PersonServiceBean() {}

    public PersonServiceBean(String user) {
        this.user = user;
    }

    public void save(String name) {
        System.out.println("我是save()方法");
    }

    public void update(String name, Integer personid) {
        System.out.println("我是update()方法");
    }

    public String getPersonName(Integer personid) {
        System.out.println("我是getPersonName()方法");
        return "xxx";
    }
}

现在提出这样一个需求:

  1. 拦截所有业务方法。
  2. 判断用户是否有权限,有权限就允许他执行业务方法,没有权限就不允许他执行业务方法。(是否有权限是根据user是否为null作为判断依据的)

为实现这样的业务需求,可能有人这样写:

public class PersonServiceBean implements PersonService {
    private String user = null;

    public String getUser() {
        return user;
    }

    public PersonServiceBean() {}

    public PersonServiceBean(String user) {
        this.user = user;
    }

    public void save(String name) {
        if (user != null) {
            System.out.println("我是save()方法");
        }
    }

    public void update(String name, Integer personid) {
        if (user != null) {
            System.out.println("我是update()方法");
        }
    }

    public String getPersonName(Integer personid) {
        if (user != null) {
            System.out.println("我是getPersonName()方法");
        }
        return "xxx";
    }
}

很显然这样做非常不妥,于是我们就要另寻他路,这个时候很容易想到动态代理技术,对于动态代理技术如有不甚清楚的,可以翻阅我的笔记动态代理(一)——动态代理入门。现在我们就使用JDK中的Proxy技术来生成PersonServiceBean对象的代理对象,但要记住在Java里面有这样一个约定:要想创建某一个对象的代理对象,那么该对象必须实现一个接口
在src目录下新建一个it.cast.aop包,并在该包下新建一个类——JDKProxyFactory.java,专门用于创建代理对象,其代码为:

public class JDKProxyFactory implements InvocationHandler {
    private Object targetObject; // 代理的目标对象

    public Object createProxyInstance(Object targetObject) {
        this.targetObject = targetObject; 
        /*
         * 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
         * 第二个参数设置代理类实现的接口
         * 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
         */
        return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), 
                this.targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        PersonServiceBean bean = (PersonServiceBean)this.targetObject;
        Object result = null;
        if (bean.getUser() != null) { // 有权限
            result = method.invoke(targetObject, args); // 把方法调用委派给目标对象
        }
        return result;
    }
}

结论:当目标类实现了一个接口,我们就可以使用JDK的Proxy来生成代理对象
最后在src目录下新建一个juint.test包,在该包下新建一个单元测试类——AOPTest.java。我们先将该类的代码写为:

public class AOPTest {

    @Test
    public void proxyTest() {
        JDKProxyFactory factory = new JDKProxyFactory();
        PersonService service = (PersonService) factory.createProxyInstance(new PersonServiceBean("xxx"));
        service.save("888");
    }

}

测试proxyTest()方法,Eclipse控制台会打印:
这里写图片描述
若将AOPTest类的代码改为:

public class AOPTest {

    @Test
    public void proxyTest() {
        JDKProxyFactory factory = new JDKProxyFactory();
        PersonService service = (PersonService) factory.createProxyInstance(new PersonServiceBean());
        service.save("888");
    }

}

再次测试proxyTest()方法,会发现Eclipse控制台什么也不会打印。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李阿昀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值