Spring(十)通过动态代理(JDK的Proxy)和cglib实现AOP技术

权限控制与代理技术在Spring框架的应用
本文探讨了在Spring框架中如何通过代理对象实现接口权限控制,具体包括使用普通代理模式和Cglib代理模式来判断用户权限并决定是否执行业务方法。通过实例演示了如何在不同场景下灵活应用这两种代理方式。

目标对象的所有接口方法

package test.spring.service;

public interface PersonService {

	public String getPersonName(Integer id);

	public void save(String name);

}

目标对象

package test.spring.service.impl;

import test.spring.service.PersonService;

//代理对象实现目标对象所有接口
public class PersonServiceBean implements PersonService {

	private String user = null;

	public PersonServiceBean() {

	}

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

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	@Override
	public String getPersonName(Integer id) {
		// TODO Auto-generated method stub
		return "getPersonName";
	}

	@Override
	public void save(String name) {
		// TODO Auto-generated method stub
		System.out.println("save()->>" + name);
	}

}

代理对象,拦截所有业务方法,根据user是否为null判断用户是否有权限,有权限就允许执行业务方法,无权限就不执行。

package test.spring.aop;

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

import test.spring.service.impl.PersonServiceBean;

public class ProxyFactory implements InvocationHandler {

	private Object proxyObject;

	// 创建代理对象实例
	public Object createProxyIntance(Object proxyObject) {
		this.proxyObject = proxyObject;
		/*
		 * 第一个参数:类装载器 
		 * 第二个参数:取得目标对象的接口,Proxy会将这些接口全部实现 
		 * 第三个参数:一个回调函数,确定实现哪个类的接口
		 */
		return Proxy.newProxyInstance(this.proxyObject.getClass()
				.getClassLoader(), this.proxyObject.getClass().getInterfaces(),
				this);
	}

	/*
	 * 第一个参数:代理对象 
	 * 第二个参数:被拦截到的方法 
	 * 第三个参数:方法的输入参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		PersonServiceBean personServiceBean = (PersonServiceBean) this.proxyObject;
		Object target = null;
		// user不为空说明有权限
		if (personServiceBean.getUser() != null) {
			// 把对代理对象方法的调用委派给目标对象
			target = method.invoke(proxyObject, args);
		}
		return target;
	}
}

权限测试

package test.spring.junit;

import static org.junit.Assert.*;

import org.junit.Test;

import test.spring.aop.ProxyFactory;
import test.spring.service.PersonService;
import test.spring.service.impl.PersonServiceBean;

public class AOPTest {

	@Test
	public void test() {
		ProxyFactory pFactory = new ProxyFactory();

		// PersonService pService=(PersonService)
		// pFactory.createProxyIntance(new PersonServiceBean("kkk"));

		// 改为默认函数pService.save("ppp")就执行不了,因为前面的user=null,相当于没有权限执行
		PersonService pService = (PersonService) pFactory
				.createProxyIntance(new PersonServiceBean());
		pService.save("ppp");
	}

}


以上适用于目标对象实现了接口的情况,如果目标对象没有接口,就会选择用Cglib

首先导入cglib-nodep-2.1_3.jar

package test.spring.service.impl;

//代理对象实现目标对象所有接口
public class PersonServiceBean2 {

	private String user = null;

	public PersonServiceBean2() {

	}

	public PersonServiceBean2(String user) {
		super();
		this.user = user;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public void save(String name) {
		// TODO Auto-generated method stub
		System.out.println("save()->>" + name);
	}

}

package test.spring.aop;

import java.lang.reflect.Method;

import test.spring.service.impl.PersonServiceBean2;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

//目标对象没有接口
public class CglibProxyFactory implements MethodInterceptor {
	private Object proxyObject;

	// 创建代理对象实例
	public Object createProxyIntance(Object proxyObject) {
		this.proxyObject = proxyObject;

		Enhancer enhancer = new Enhancer();
		/*
		 * 需设置父类,即目标类。创建的对象继承目标类,对目标类中
		 * 所有非final的所有方法进行覆盖,然后在覆盖的代码里面
		 * 添加一些自身的代码
		 */
		enhancer.setSuperclass(this.proxyObject.getClass());
		enhancer.setCallback((Callback) this);
		return enhancer.create();

	}

	/*
	 * 第一个参数:代理对象本身 
	 * 第二个参数:被拦截到的方法 
	 * 第三个参数:方法的参数 
	 * 第四个参数:方法的代理对象
	 */
	// 当代理对象的业务方法被回调的时候会调用这个方法
	@Override
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		PersonServiceBean2 personServiceBean = (PersonServiceBean2) this.proxyObject;
		Object target = null;
		// user不为空说明有权限
		if (personServiceBean.getUser() != null) {
			// 把对方法的调用委派给目标对象
			target = methodProxy.invoke(proxyObject, args);
		}
		return target;
	}
}

package test.spring.junit;

import static org.junit.Assert.*;

import org.junit.Test;

import test.spring.aop.CglibProxyFactory;
import test.spring.aop.ProxyFactory;
import test.spring.service.PersonService;
import test.spring.service.impl.PersonServiceBean;
import test.spring.service.impl.PersonServiceBean2;

public class AOPTest2 {

	@Test
	public void test() {
		CglibProxyFactory pFactory = new CglibProxyFactory();

		// 此时PersonServiceBean没有接口
		PersonServiceBean2 pService = (PersonServiceBean2) pFactory
				.createProxyIntance(new PersonServiceBean2("kkk"));

		pService.save("ppp");
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

设计师Linda

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

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

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

打赏作者

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

抵扣说明:

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

余额充值