五分钟学会JAVA设计模式-代理模式

(设计模式-代理模式)

代理模式分三种

JDK静态代理、JDK动态代理和CGLIB动态代理

代理模式能做什么?

Spring中的AOP是离不开代理模式的

Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理。
不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

动态代理能够在被代理的类的方法执行前和执行后进行处理,主要用来解决一些系统层面上的问题
比如日志,事务,权限等

静态代理

静态代理实现方法
实现原理:
就是创建一个代理类,代理类和被代理类实现同一个接口,将被代理类以构造参数的方法传入代理类
调用代理类的方法时,代理类先调用自己的方法再调用被代理类的方法,然后再调用自己的方法

public class Proxy implements IUserService{
	private IUserService userService;			//将需要被代理的类创建出来
	public Proxy(IUserService userService)
	{
		this.userService=userService;			//赋值被代理的类
	}
	@Override
	public void insertRandomUser() {
		System.err.println("执行前");			//执行前处理
		userService.insertRandomUser();
		System.err.println("执行后");			//执行后处理
	}

	@Override
	public void printlnRandomUser() {
		System.err.println("执行前");			//执行前处理
		userService.printlnRandomUser();
		System.err.println("执行后");			//执行后处理
	}
	public static void main(String[] args) {
		Proxy proxy=new Proxy(new UserService());		//创建被代理的类和代理类
		proxy.insertRandomUser();									//代理类执行
		proxy.printlnRandomUser();								//代理类执行
	}

jdk动态代理

使用jdk动态代理时我们需要先创建一个接口、一个继承该接口的类和一个代理类
(如:接口 IUserService、继承类UserService、代理类ProxyPattern)

为了更容易理解代理模式,我在里面还添加了一个User类

//User类
public class User {
	private String name;
	private Integer age;
	private Boolean sex;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Boolean getSex() {
		return sex;
	}
	public void setSex(Boolean sex) {
		this.sex = sex;
	}
	
	@Override
	public String toString() {
		return "name="+name+",age="+age+",sex="+sex;
	}
}

这是接口 IUserService
接口中定义了两个方法

//接口
public interface IUserService {
		//添加user对象
		void insertRandomUser();
		//删除user对象
		void printlnRandomUser();
}

这是继承类了接口的 UserService 类
类中对两个接口进行了实现并且添加了一个静态变量userList

//继承类
public class UserService implements IUserService {
	//用来保存user对象
	private static List<User> userList=new ArrayList<User>();
	public void insertRandomUser() {
		User user=new User();
		int size=userList.size();
		user.setAge(new Random().nextInt(100));
		user.setName(String.valueOf(new Random().nextInt(100)));
		user.setSex(new Random().nextBoolean());
		userList.add(user);
		System.err.println("添加成功,剩余对象"+(size-1));
		System.err.println(user.toString());
	}

	public void printlnRandomUser() {
		int size=userList.size();
		if(size<=0)
		{
			System.err.println("没有对象了");
			return;
		}
		System.err.println("取出成功,剩余对象"+(size-1));
		int number=new Random().nextInt(size);
		User user=userList.get(number);
		userList.remove(number);
		System.err.println(user.toString());
	}
}

最后是代理类

public class ProxyPattern<T> implements InvocationHandler  {
	private static int proxyNum=0;
	private T obj;
    public ProxyPattern(T obj) {
        this.obj = obj;
    }
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("代理执行" + method.getName() + "方法");
        Object result = method.invoke(obj, args);
        System.out.println("方法" + method.getName() + "执行完毕");
        proxyNum++;
        System.out.println("当前类执行了"+proxyNum+"次");
        return result;
	}
		public static void main(String[] args) {
			IUserService userServce=new UserService();
	        InvocationHandler handler = new ProxyPattern<IUserService>(userServce);
	        IUserService moveable = (IUserService) Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class<?>[] {IUserService.class} , handler);
	        while(true)
	        {
	        	try {
					Thread.sleep(1000);
					if(new Random().nextBoolean())
					{
						moveable.insertRandomUser();
					}
					else
					{
						moveable.printlnRandomUser();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
	        }
	        
		}
}

CGLIB 动态代理

CGLIB jar包下载地址

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

cglib 动态代理实现
cglib 的实现和jdk的实现是极其相似的,jdk动态代理是基于接口进行实现,cglib则是基于类实现
在spring的AOP中,需要被代理的类是接口则采用jdk的实现,需要被代理的类不是接口则采用cglib的实现

public class CGLIBProxyPattern implements MethodInterceptor{

    public static void main(String[] args) {
        UserService userService = new UserService();  						//创建service层对象
        CGLIBProxyPattern cglib = new CGLIBProxyPattern();			//创建代理对象
        Enhancer enhancer = new Enhancer();										//创建代理类创建器
        enhancer.setSuperclass(userService.getClass());						//设置创建类型为UserService。class
        enhancer.setCallback(cglib);													//设置代理对象(代理对象需要继承MethodInterceptor接口)
        IUserService hose = (IUserService) enhancer.create();			//创建代理后的对象
        hose.insertRandomUser();														//调用方法
        hose.printlnRandomUser();														//调用方法

    }

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			System.out.println("执行前");												//调用方法前执行
	        Object o = methodProxy.invokeSuper(obj, args);				//调用原方法
	        System.out.println("执行后");												//调用方法后执行
	        return o;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值