这个是在上一个视频的基础上来进行是实现的。首先就是有一个BeanFactory来进行总的整合,在这个类里面有个方法getBean参数就是传入的name,该名称在属性文件中有标记。这个方法返回一个bean或者一个代理的实例对象。
package springFrame;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import test.Advice;
public class BeanFactory {
Properties pro = new Properties();
public BeanFactory(InputStream ips){
try {
pro.load(ips);//加载属性文件
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String name){
//获得这个是目标bean还是代理bean
String className = pro.getProperty(name);
//从属性文件中得到名字是name对应的名称
Object bean = null;
try {
Class clazz = Class.forName(className);
//通过这个名称获得该名称对应的类的字节码
bean = clazz.newInstance();
//该类进行实例化
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean){
//如果这个bean是代理类
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
//转化为这个代理的bean
Advice advice = null;
Object target = null;
try {
advice = (Advice)Class.forName(pro.getProperty(name + ".advice")).newInstance();
//契约实例化通过属性文件得到的名称
target = Class.forName(pro.getProperty(name + ".target")).newInstance();
//目标的实例化通过属性文件中得到的名称
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
proxyFactoryBean.setTarget(target);
//把这个目标类设置到代理类的bean中
proxyFactoryBean.setAdvice(advice);
//把契约类设置到代理类的bean中
Object proxy = proxyFactoryBean.getProxy();
//通过代理类的bean来获得这个代理的类的实例对象并返回
return proxy;
}
return bean;
}
}
上面的代码是BeanFactory,通过它就可以得到我们想要的是bean还是代理。
package springFrame;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import test.Advice;
public class ProxyFactoryBean {
private Object target;//定义目标类
private Advice advice;//定义契约
public Object getProxy(){
Object proxy3 = Proxy.newProxyInstance(//实例化一个代理
target.getClass().getClassLoader(), //传入目标的加载器
target.getClass().getInterfaces(), //传入目标的接口
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);//执行契约类的的before方法
Object revalue = method.invoke(target, args);
advice.afterMethod(method);//执行契约类的after方法
return revalue;//返回给代理
}
});
return proxy3;//返回一个代理
}
public Object getTarget() {//获得目标
return target;
}
public void setTarget(Object target) {//设置目标
this.target = target;
}
public Advice getAdvice() {//获得契约
return advice;
}
public void setAdvice(Advice advice) {//设置契约
this.advice = advice;
}
}
这个是代理类的生成工厂,在这个类里面我们要有两个传入的参数,才能正确的生成目标类的代理,一个是目标另外就是契约。契约是上次笔记中就有,主要是我们要加入的系统功能的实现。
然后就是测试:
package springFrame;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
public class AopFrameworkTest {
public static void main(String[] args) throws Exception,
IllegalAccessException {
InputStream ips = AopFrameworkTest.class
.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
Collection c = (Collection)bean;//由于这个是代理,所以要通过接口Collection来获得
c.add("1");
c.size();
System.out.println(bean.getClass().getName());
}
}
最后测试的结果很正常,输出了这个代理类的名称和执行add的时候会把我们契约中要加入的功能也已经加入了进去。