工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
目标
通知
编写客户端应用:
编写实现Advice接口的类和在配置文件中进行配置
调用BeanFactory获取对象
class BeanFactory负责创建目标类或代理类的实例对象
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.heima.day3.Advice;
public class BeanFactory {
Properties propers = new Properties();
BeanFactory(InputStream in){
try {
propers.load(in);//将流读取的内容加载到Properties容器中,键值对
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name){//通过该方法获得目标类或代理类
Object bean = null;
String clazzName = propers.getProperty(name);//根据传入的参数获得在propers中的对应的值
try {
Class clazzProxy = Class.forName(clazzName);//知道目标类的字符串名称,通过名称获得字节码
bean = clazzProxy.newInstance();//调用字节码对应类的构造函数,创建一个对象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean ){//判断创建的对象是否是应该添加代理的代理类
Object proxy= null;
try {
ProxyFactoryBean proxyBean = (ProxyFactoryBean)bean;//强制转换成代理类
Advice advice = (Advice)Class.forName(propers.getProperty(name+".advice")).newInstance();//配置文件信息
Object target = Class.forName(propers.getProperty(name+".target")).newInstance();//配置文件中的目标类信息
proxyBean.setAdvice(advice);//添加系统功能
proxyBean.setTarget(target);//添加目标类
proxy = proxyBean.getProxy();//通过ProxyFactoryBean的getProxy方法获取代理类对象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return proxy;//返回代理类对象
}
return bean;//不是应添加代理的,返回目标类对象
}
}
class ProxyFactoryBean
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.heima.day3.Advice;
public class ProxyFactoryBean {
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 Advice advice ;
private Object target ;
public Object getProxy() {//获取代理类对象
// TODO Auto-generated method stub
Object proxy3 = 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 retVal;
}
}
);
return proxy3;//返回代理类对象
}
}
FactoryBeanTest
import java.io.InputStream;
import java.util.Collection;
public class FactoryBeanTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
InputStream in = FactoryBeanTest.class.getResourceAsStream("config.properties");//读取当前路径下的配置文件
Object bean = new BeanFactory(in).getBean("xxx");//将配置文件的键传入,
System.out.println(bean.getClass());
Collection beans = (Collection)bean;
beans.clear();
}
}
Advice
import java.lang.reflect.Method;
public interface Advice {
public void beforeMethod(Method method);
public void afterMethod(Method method);
}
MyAdvice
public class MyAdvice implements Advice {
long startTime;
public void beforeMethod(Method method) {
startTime = System.currentTimeMillis();//开始时间
}
public MyAdvice() {
super();
}
public void afterMethod(Method method){
long endTime = System.currentTimeMillis();//结束时间
System.out.println(method.getName()+"...time.."+(endTime-startTime));//运行的时间
}
}
配置文件信息
#xxx=java.util.ArrayList
xxx=ProxyFactoryBean
xxx.advice=MyAdvice
xxx.target=java.util.ArrayList