AOP之静态代理VS动态代理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010097777/article/details/51598132

一、代理概念

        为某个对象提供一个代理,以控制对这个对象的访问。代理类和委托类有共同的父类或父接口,代理类负责请求的预处理,过滤,将请求分配给委托类处理。

二、静态代理:

         由程序员创建或工具生成代理类的源码,再编译代理类,即代理类和委托类的关系再程序运行前就已经存在。现有一User接口,对user的增删改查,User的实现里面分别有对每个方法的安全性检查,使用静态代理实现:

UserManager:

package com.bjpowernode.spring;

public interface UserManager {

	public void addUser(String username, String password);
	
	public void delUser(int userId);
	
	public String findUserById(int userId);
	
	public void modifyUser(int userId, String username, String password);
}

UserManagerImpl:

package com.bjpowernode.spring;

public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {
		<span style="color:#ff0000;">checkSecurity();</span>
		System.out.println("---------UserManagerImpl.add()--------");
	}

	public void delUser(int userId) {
		<span style="color:#ff0000;">checkSecurity();</span>
		System.out.println("---------UserManagerImpl.delUser()--------");
	}

	public String findUserById(int userId) {
		<span style="color:#ff0000;">checkSecurity();</span>
		System.out.println("---------UserManagerImpl.findUserById()--------");</span>
		<span style="font-size:18px;">return "张三";
	}

	public void modifyUser(int userId, String username, String password) {
		<span style="color:#ff0000;">checkSecurity();</span>
		System.out.println("---------UserManagerImpl.modifyUser()--------");
	}

	private void <span style="color:#cc0000;">checkSecurity()</span> {
		System.out.println("-------checkSecurity-------");
	}
}

UserManagerImplProxy:

package com.bjpowernode.spring;

public class UserManagerImplProxy implements UserManager {
       //目标对象
      private UserManager userManager;
      //通过构造方法传入目标对象
      publicUserManagerImplProxy (UserManager userManager){                            
           this.userManager=userManager;
      }

	public void addUser(String username, String password) {
          try{  
            //添加打印日志的功能
             //开始添加用户          
                  System.out.println("start-->addUser()"); 
                  userManager.addUser(userId, userName);           
            //添加用户成功
                   System.out.println("success-->addUser()"); 
            }catch(Exception e){              
             //添加用户失败             
             System.out.println("error-->addUser()"); }  
	    }

	public void delUser(int userId) {
	    userManager.delUser(userId);
	}

	public String findUserById(int userId) {
		userManager.findUserById(userId);
             return"张三";
	}

	public void modifyUser(int userId, String username, String password) {
	  userManager.modifyUser(userId,userName); 
	}	 
}

可以看出,如果对User每个方法进行安全性验证,存在两个问题:一、在User的实现类中每个方法中都要调用,客户端如果测试,直接new一个UserManagerImpl。二、每个代理类只能实现一个接口,如果业务复杂,就会产生许多的代理类,所以想办法通过一个代理类完成全部代理功能,动态代理出现。java中实现动态代理机制,需要java.lang.reflect.InvocationHandler 接口和 java.lang.reflect.Proxy 类的支持。

三、动态代理

java.lang.reflect.InvocationHandler接口的定义如下:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

Object proxy:被代理的对象

Method method:要调用的方法

Object[] args:方法调用时所需要参数

java.lang.reflect.Proxy类的定义如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

CLassLoader loader:类的加载器

Class<?> interfaces:得到全部的接口

InvocationHandler h:得到InvocationHandler接口的子类的实例

UserManagerImpl,其中UserManager同上:

package com.bjpowernode.spring;

public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {		
		System.out.println("---------UserManagerImpl.add()--------");
	}

	public void delUser(int userId) {		
		System.out.println("---------UserManagerImpl.delUser()--------");
	}

	public String findUserById(int userId) {		
		System.out.println("---------UserManagerImpl.findUserById()--------");
		return "张三";
	}

	public void modifyUser(int userId, String username, String password) {		
		System.out.println("---------UserManagerImpl.modifyUser()--------");
	}
}

SecurityHandler实现:

package com.bjpowernode.spring;

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

public class SecurityHandler implements InvocationHandler {
	
	private Object targetObject;
	
	public Object createProxyInstance(Object targetObject) {
		this.targetObject = targetObject;//取得代理对象
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
							   targetObject.getClass().getInterfaces(), 
							   this);
	}
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		checkSecurity();
		
		//调用目标方法
		Object ret = method.invoke(targetObject, args);
		
		return ret;
	}
	
	private void checkSecurity() {
		System.out.println("-------checkSecurity-------");
	}		
}

Client调用:

package com.bjpowernode.spring;

public class Client {

	public static void main(String[] args) {
		SecurityHandler hander = new SecurityHandler();
		UserManager useraManager = (UserManager)hander.createProxyInstance(new UserManagerImpl());
		useraManager.addUser("张三", "123");
	}
}

       这样可以看出,动态代理把散落在程序角落的方法都放在一个类里面。它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。

展开阅读全文

没有更多推荐了,返回首页