JAVA中实现简单的AOP框架功能

前言

原创文章欢迎转载,请保留出处。
若有任何疑问建议,欢迎回复。
邮箱: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方法,更加灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值