您的位置:首页 > 编程语言 > Java开发

java反射代理技术

2013-08-30 03:09 288 查看

静态代理

package senssic.demo;

/**
 * 静态代理
 * 
 * @author Administrator
 * 
 */
interface AFace {// 接口
	public void say();
}

class BClass implements AFace {// 实际类

	@Override
	public void say() {
		System.out.println("hello word!");
	}

}

class PBClass implements AFace {// 代理类
	private final BClass bClass;

	public PBClass(BClass bClass) {
		this.bClass = bClass;
	}

	@Override
	public void say() {
		// TODO Auto-generated method stub
		System.out.println("运行实际类方法前可发生的事情…………");
		this.bClass.say();
		System.out.println("运行实际类方法后可发生的事情…………");
	}

}

public class PoxyClass {
	public static void main(String[] args) {
		AFace aFace = new PBClass(new BClass());
		aFace.say();
	}

}

缺点:

一个代理类只能为一个接口服务,所以我们接下来使用动态代理

jdk的动态

package senssic.demo;

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

/**
 * 动态代理
 * 
 * @param args
 */
interface BFace {// 接口
	public void say();
}

class BClass implements BFace {// 真实类

	@Override
	public void say() {
		System.out.println("hello word!");
	}

}

class DPClass implements InvocationHandler {// 动态代理类必须实现InvocationHandler接口并实现invoke方法确定实现的类
	private Object object;

	public Object bind(Object object) {
		this.object = object;
		return Proxy.newProxyInstance(object.getClass().getClassLoader(),
				object.getClass().getInterfaces(), this);// 使用反射代理类Proxy实例化代理的接口(必须绑定接口),如果想代理没有接口的类需要使用cglib包
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)// 调用对应的方法
			throws Throwable {
		System.out.println("运行实际类方法前可发生的事情…………");
		Object temp = method.invoke(this.object, args);
		System.out.println("运行实际类方法后可发生的事情…………");
		return temp;
	}

}

public class DPoxyClass {

	public static void main(String[] args) {
		BFace bFace = (BFace) new DPClass().bind(new BClass());
		bFace.say();
	}

}


优点:可以动态的代理,不限于接口的类型

缺点:必须绑定接口,即代理的类必须要实现接口,如果代理未实现接口的类我们需要apache的cglib包

外包的动态代理

下载地址: http://cglib.sourceforge.net/
package senssic.demo;

import java.lang.reflect.Method;

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

class CClass {// 实际类
	public void say() {
		System.out.println("hello word!");
	}

}

class CPlass implements MethodInterceptor {// 代理类,必须实现MenthodInterceptor接口通过反射调用实际方法
	private Object object;

	public Object bind(Object object) {// 绑定操作设置对应的实际类
		this.object = object;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.object.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] objects,
			MethodProxy proxy) throws Throwable {
		System.out.println("运行实际类方法前可发生的事情…………");
		Object temp = proxy.invokeSuper(obj, objects);// 反射调用实际类方法
		System.out.println("运行实际类方法后可发生的事情…………");
		return temp;
	}
}

public class CPClass {
	public static void main(String[] args) {
		CPlass cPlass = new CPlass();
		CClass cClass = (CClass) cPlass.bind(new CClass());
		cClass.say();

	}

}
Cglib动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

仿spring原理的实现

package senssic.demo;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;

interface DFace {//实际类接口
	public void say();
}

class DClass implements DFace {//实际类,因为是jdk动态代理所以必须有实现接口
	@Override
	public void say() {
		System.out.println("hello word!");
	}
}

class BeanFactory {// bean工厂
	Properties pros = new Properties();

	public BeanFactory(InputStream ips) {
		try {
			pros.load(ips);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public Object getBean(String name) {
		String className = pros.getProperty(name);
		Class cla = null;
		Object bean = null;
		try {
			cla = Class.forName(className);
			bean = cla.newInstance();

			if (bean instanceof ProxyFactoryBean) {
				ProxyFactoryBean pFactoryBean = (ProxyFactoryBean) bean;
				Adivce advice = (Adivce) Class.forName(
						pros.getProperty(name + ".advice")).newInstance();
				Object target = Class.forName(
						pros.getProperty(name + ".target")).newInstance();
				pFactoryBean.setAdvice(advice);
				pFactoryBean.setTarget(target);
				Object proxy = pFactoryBean.getProxy();
				return proxy;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return bean;

	}
}

class ProxyFactoryBean {//业务处理类
	private Adivce advice;
	private Object target;

	public Adivce getAdvice() {
		return advice;
	}

	public void setAdvice(Adivce advice) {
		this.advice = advice;
	}

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	public Object getProxy() {
		Object temp = Proxy.newProxyInstance(
				target.getClass().getClassLoader(), target.getClass()
						.getInterfaces(), new InvocationHandler() {

					@Override
					public Object invoke(Object obj, Method method,
							Object[] objects) throws Throwable {
						advice.before();
						Object object = method.invoke(target, objects);
						advice.after();
						return object;
					}
				});
		return temp;
	}

}

class Adivce {
	public void before() {
		System.out.println("运行实际类方法前可发生的事情…………");
	}

	public void after() {
		System.out.println("运行实际类方法后可发生的事情…………");
	}

}

public class SClass {

	public static void main(String[] args) {
		InputStream ips = SClass.class.getResourceAsStream("config.properties");
		DFace bean = (DFace) new BeanFactory(ips).getBean("xxx");//动态代理类只能被转换为对应的接口,不能转换为实现类
		bean.say();
	}
}


配置文件为:在同一目录下,文件名:config.properties
#xxx=java.util.ArrayList

xxx=senssic.demo.ProxyFactoryBean

xxx.advice=senssic.demo.Adivce

xxx.target=senssic.demo.DClass

运行结果:
运行实际类方法前可发生的事情…………

hello word!

运行实际类方法后可发生的事情…………
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: