Java代理机制

一、静态代理。(在代理类构造方法中引用被代理类的对象)

被代理类接口

public interface Subject {
	public void say();
}

被代理类

public class RealSubject implements Subject {

	@Override
	public void say() {
		System.out.println("Hello Real Subject .....");
	}

}

代理类

public class ProxySubject implements Subject {
	
	private Subject sub;
	
	@Override
	public void say() {
		sub.say();
	}
	
	public ProxySubject(Object obj){
		this.sub = (Subject) obj;
	}

}

测试类

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Subject sub = new RealSubject();
		sub.say();
		
		Subject proxySub = (Subject)new ProxySubject(new RealSubject());
		proxySub.say();
	}
}


【注】我觉得吧,既然创建了RealSubject的对象,代理也就没什么意义吧。直接sub.say()不就完了吗。我觉得在ProxySubject里面用发射可能更好理解。

二、动态代理(BeanUtil)

采用 JDK 的反射机制和动态代理生成了代理对象 , 并进行方法拦截 )
被代理类接口

package DongTai.BeanUtil;

public interface IAction {
	public void doProcess();
}
被代理类

package DongTai.BeanUtil;

public class ActionImpl implements IAction {

	@Override
	public void doProcess() {

	}

}
代理工厂

package DongTai.BeanUtil;

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

public class ProxyFactory implements InvocationHandler{
	private Object targetObject ;

	   

    public Object createProxyInstance(Object targetObject) {

       this.targetObject = targetObject;
       
       Class cl = Proxy.getProxyClass(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces());
       System.out.println(cl.getName());
       
       return Proxy.newProxyInstance (targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this );

       /*Class cl = getProxyClass(loader, interfaces);//返回一个interfaces的接口实现类
       Constructor cons = cl.getConstructor(constructorParams);
       //返回实现类里面的一个构造方法
       // constructorParams的定义为:private final static Class[] constructorParams = {InvocationHandler.class};
       return (Object)cons.newInstance(new Object[]{h});
       //执行这个构造方法返回一个对象(里面肯定执行了h.invoke(....))*/
    }

 

    @Override

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

           throws Throwable {

       IAction action = (IAction) targetObject ;

       Object result = null ;

       try {

           System. out .println( " 检查权限 ......." );
           //反射
           result = method.invoke(action, args);

           System. out .println( " 检查权限完毕 ...." );

       } catch (Exception e) {

           System. out .println( " 运行时发生异常 ..." );

       } finally {

           System. out .println( " 调用结束 ..." );

       }

       return result;

    }
}
【注】通过打印发现Class cl 的名称是$Proxy0 ,看不懂这里。大致理解是第一步返回一个接口实现类,第二步是获取其中的一个构造方法,第三步是执行构造方法(里面调用当前代理工厂中的invoke方法,这个invoke方法里面通过反射执行被代理类中的方法.....也就是上面我的疑问)

测试类

package DongTai.BeanUtil;

public class App {
	public static void main(String[] args) {

	       ProxyFactory factory = new ProxyFactory();

	       IAction action = (IAction)factory.createProxyInstance( new ActionImpl());

	       action.doProcess ();

	    }
}

三、动态代理(cglib)

(BeanUtil 对于没有实现接口的类不能采用以上方法产生代理类,此时可以用 cglib  jar 包,这里采用 cglib-nodep-2.1_3.jar )
代理工厂

package DongTai.Cglib;

import java.lang.reflect.Method;

public class CglibProxyFactory implements MethodInterceptor{
	 private Object targetObject ;

	   

	    public Object createProxyInstance(Object targetObject) {

	       this . targetObject = targetObject;

	       Enhancer enhancer = new Enhancer();

	       enhancer.setSuperclass(targetObject.getClass());

	       enhancer.setCallback( this );

	       return enhancer.create();

	    }

	 

	    @Override

	    public Object intercept(Object proxy, Method method, Object[] args,

	           MethodProxy methodproxy) throws Throwable {

	       Object result = null ;

	       try {

	           System. out .println( " 检查权限 ......." );

	           result = methodproxy.invoke( targetObject , args);

	           System. out .println( " 检查权限完毕 ...." );

	       } catch (Exception e) {

	           System. out .println( " 运行时发生异常 ..." );

	       } finally {

	           System. out .println( " 调用结束 ..." );

	       }

	       return result;

	    }
}

测试类

package DongTai.Cglib;

public class App {
	public static void main(String[] args) {

	       CglibProxyFactory factory = new CglibProxyFactory();

	       ActionImpl action = (ActionImpl)factory.createProxyInstance( new ActionImpl());

	       action.doProcess();

	    }
}
【注】是不是有点熟悉了?我们在Struts2框架中定义的拦截器也是使用了MethodInterceptor

Spring当中提供了两种实例化方案:  BeanUtils  和  Cglib  方式。BeanUtils实现机制是通过Java的反射机制,Cglib是一个第三方类库采用的是一种字节码加强方式机制。  Spring中采用的默认实例化策略是Cglib。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值