前言
原创文章欢迎转载,请保留出处。
若有任何疑问建议,欢迎回复。
邮箱:Maxwell_nc@163.com
通过写一个工厂类BeanFactory负责创建配置文件config.properties中指定的目标类或者代理类的实例对象,类中方法getBean根据参数传入的字符串返回一个相应的实例对象,如果该类名是ProxyFactoryBean类则创建代理类的实例对象,否则直接调用目标类的不带参数的构造方法创建实例对象并返回,实现类似Spring框架的AOP功能。
BeanFactory类分析及代码
这个类主要通过构造方法传入一个输入流接收配置文件,另外一个主要方法getBean是整个框架的核心。这个方法先获取配置文件中需要创建的类的名字,然后先调用不带参数的构造方法创建一个实例对象(配置中的要求创建的类必须是JavaBean,否则不一定具有不带参数的构造方法),通过实例对象判断是否是ProxyFactoryBean对象,如果是,则转换成ProxyFactoryBean对象,调用ProxyFactoryBean类中方法getProxy来创建代理对象。
package maxwell_nc.aopframework;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
Properties props = new Properties();
public BeanFactory(InputStream ips){
try {
props.load(ips);//读入配置文件
} catch (IOException e) {
e.printStackTrace();
}
}
public Object getBean(String key){
//这个方法的用途是:获得一个key所指的类对象,
//如果这个类是ProxyFactoryBean类的,即代理类,则创建代理对象并返回
//如果不是则直接调用不带参数的构造方法创建对象返回
String clazzname = props.getProperty(key);
Object bean = null;
try {
Class clazz = Class.forName(clazzname);
bean = clazz.newInstance();//对于javabean必须有不带参数的构造方法
} catch (Exception e) {
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean)
{
//转换成ProxyFactoryBean对象,方便使用getProxy方法和set方法
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
Object proxy = null;
try {
//取得所想建立的对象目标和Advice类
Object target = Class.forName(props.getProperty(key+".target")).newInstance();
Advice ad = (Advice)Class.forName(props.getProperty(key+".advice")).newInstance();
proxyFactoryBean.setTarget(target);
proxyFactoryBean.setAd(ad);
proxy = proxyFactoryBean.getProxy();
} catch (Exception ex) {
ex.printStackTrace();
}
return proxy;
}
return bean;
}
}
ProxyFactoryBean类分析及代码
核心是getProxy利用Proxy类的静态方法newProxyInstance创建代理对象,覆盖了invoke方法,利用InvocationHandler处理方法调用。invoke方法中间插入了Advice实现类。
package maxwell_nc.aopframework;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
public class ProxyFactoryBean {
private Object target;
private Advice ad;
public Object getProxy() {
//利用Proxy类的静态方法newProxyInstance创建代理对象
Object proxyobj = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ad.beforeMethod(method);
Object obj = method.invoke(target, args);
ad.afterMethod(method);
return obj;
}
}
);
return proxyobj;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAd() {
return ad;
}
public void setAd(Advice ad) {
this.ad = ad;
}
}
Advice接口及实现类
这个不用解析了,直接给代码,Advice接口
package maxwell_nc.aopframework;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method);
void afterMethod(Method method);
}
Advice实现类
package maxwell_nc.aopframework;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
@Override
public void afterMethod(Method method) {
System.out.println(method.getName()+"_start");
}
@Override
public void beforeMethod(Method method) {
System.out.println(method.getName()+"_end");
}
}
测试类和配置文件
这里我们用一个单独类来测试,我们先写一个config.properties文件
#bean=java.util.ArrayList
bean=maxwell_nc.aopframework.ProxyFactoryBean
bean.target=java.util.ArrayList
bean.advice=maxwell_nc.aopframework.MyAdvice
注意,如果使用第一行代表使用普通的bean,第二行则是创建ProxyFactoryBean,可以分别注释进行测试。下面是测试类
package maxwell_nc.aopframework;
import java.io.InputStream;
import java.util.Collection;
public class AopFrameworkTest {
public static void main(String[] args) {
InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
//创建工厂
BeanFactory beanFactory = new BeanFactory(ips);
//获取对象并打印对应字节码名字
Object bean = beanFactory.getBean("bean");
System.out.println(bean.getClass().getName());
//下面语句可以测试Advice类是否有效
//((Collection)bean).clear();
}
}
我们把尝试创建代理对象,并在Myeclipse中测试结果:正常获得代理对象并且调用了Advice类功能。
总结
实际上还可以把ProxyFactoryBean定义成一个接口,有许多实现这个接口的bean类,对每一个进行判断,每一种bean类都有自己的getProxy方法,更加灵活。