要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
要为系统中的各种接口的类增加代理功能,拿将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情。
JVM可以在运行期间动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或者多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现几口的类生成动态代理类,那么可以使用CGLIB库。
想让JVM生成动态类,可以使用Proxy提供newProxyInstance方法。
BeanFactory类
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
//创建Properties对象,要加载配置文件读入
Properties prop= new Properties();
//使用构造方法加载配置文件
public BeanFactory(InputStream ips){
try {
prop.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//定义获取Bean对象的方法,并传入名字
public Object getBean(String name)throws Exception{
//从配置文件中获取类名
String className=prop.getProperty(name);
//创建类的对象
Class clazz=Class.forName(className);
Object bean=clazz.newInstance();
//如果获取的对象是属于ProxyFactoryBean就使用它的getProxty方法得到代理类
if(bean instanceof ProxyFactoryBean){
ProxyFactoryBean proxyFactoryBean=(ProxyFactoryBean)bean;
//传入advice对象
Advice advice=(Advice)(Class.forName(prop.getProperty(name+".advice")).newInstance());
//传入target对象
Object target=Class.forName(prop.getProperty(name+".target")).newInstance();
//使用getProxy方法获取代理类
Object proxy=proxyFactoryBean.getProxy();
return proxy;
}
//如果获取的对象就是Bean类,就返回对象
return bean;
}
}
ProxyBeanFactory类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactoryBean {
private Advice advice;
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
private Object target;
public Object getProxy() {
//使用代理类的构造方法创建代理类对象
Object proxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
advice.beforeMethod(method);
Object retVal=method.invoke(target, args);
advice.afterMethod(method);
return null;
}
});
return proxy;
}
}
学习感悟:代理类是JVM按照设计者的要求自动创建动态类,JAVA的功能真是太强大了,还有好多地方需要学习。