java反射代理技术

静态代理

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!
运行实际类方法后可发生的事情…………


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值