自定义实现 IOC

对IOC和AOP的概念了解清楚了,那么如何运用它们呢?
这里我们来通过一个银行转帐的demo来进行自定义IOC以及AOP的实现。

首先,我们实体类代码如下:

public class BankAccount {

    //卡号
    private String cardNo;
    //姓名
    private String name;
    //余额
    private int money;


    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

dao层代码

public interface BankAccountDao {
    //查询
    BankAccount query(String carNo) throws SQLException;
    //更新
    void update(BankAccount to) throws SQLException;
}

service层:

public interface TransferService {
    //转账
    void transfer(String fromCardNo, String toCardNo, int money) throws SQLException;
}

service实现类:

public class TransferServiceImpl implements TransferService {
	//转账具体实现
    @Override
    public void transfer(String fromCardNo, String toCardNo, int money) throws SQLException {

        try {
			BankAccountDao bankAccountDao=new BankAccountDaoImpl();
            BankAccount from = bankAccountDao.query(fromCardNo);
            BankAccount to = bankAccountDao.query(toCardNo);

            from.setMoney(from.getMoney() - money);
            to.setMoney(to.getMoney() + money);

            bankAccountDao.update(to);
            bankAccountDao.update(from);

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

    }

}

以上业务代码中,可以看出在 service实现类中,要想对对象进行持久化操作,则必须要new一个Dao层实现类的对象,这就造成了类TransferServiceImpl与类BankAccountDaoImpl之间耦合,如果业务比较复杂,那么所有的操作都需要把Dao层对象new出来,这就不利于系统代码到维护。

那么,我们怎么样来实现IOC来管理对象呢?

IOC既然帮我们new对象,那么需要new哪个对象肯定需要告诉容器,
这些我们可以在配置文件中进行约定,然后在加载的时候,容器读取到配置文件进行获取。
那么,这些new出来后,肯定需要存储,在这里我们用一个 HashMap集合进行对象的存储。

下面,我们先创建一个配置文件,取名 beans.xml,
根节点为 < beans >
字节点 < bean > 代表每个要管理到对象
< bean>中
id :类的标记,当作map中获取bean的key
class:全类限定名,然后可以通过反射来实现对象的实例化

如果对象A中包含另外一个对象B的时候呢?
我们在每个< bean>中添加子节点< property>来维护对象之间的依赖关系
< property>中:
name:代表着依赖对象中对名称,我们可以通过set方法注入,所以这里要和set方法名称去掉set后一致就行了
ref:告诉容器,这个要注入的对象的key

<?xml version="1.0" encoding="utf-8" ?>
<beans>


    <!--数据库连接工具类-->
    <bean id="connectionUtils" class="com.lcg.edu.utils.ConnectionUtils">

    </bean>
    
    <!--dao-->
    <bean id="bankAccountDao" class="com.lcg.edu.dao.impl.BankAccountDaoImpl">
        <property name="ConnectionUtils" ref="connectionUtils"></property>
    </bean>

    <!--service-->
    <bean id="transferService" class="com.lcg.edu.service.impl.TransferServiceImpl">
        <property name="BankAccountDao" ref="bankAccountDao"></property>
    </bean>

    <!--事务管理器-->
    <bean id="transactionManager" class="com.lcg.edu.utils.TransactionManager">
        <property name="ConnectionUtils" ref="connectionUtils"></property>
    </bean>

    <!--代理对象工厂-->
    <bean id="proxyFactory" class="com.lcg.edu.factory.ProxyFactory">
        <property name="TransactionManager" ref="transactionManager"></property>
    </bean>

</beans>

都准备好了以后,那么就新建一个BeanFactory工厂类,进行管理对象。
BeanFactory有两个任务,
* 任务一:读取解析xml,通过反射技术实例化对象并且存储待用(map集合)
* 任务二:对外提供获取实例对象的接口(根据id获取)

public class BeanFactory {

    /**
     * 任务一:读取解析xml,通过反射技术实例化对象并且存储待用(map集合)
     * 任务二:对外提供获取实例对象的接口(根据id获取)
     */

    //bean容器
    private static Map<String, Object> map = new HashMap();

    //任务1,解析加载xml配置到map中

    static {
        InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");


        SAXReader saxReader = new SAXReader();
        try {
            //解析xml
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();


            //解析bean
            List<Element> beanList = rootElement.selectNodes("//bean");
            for (Element element : beanList) {
                //获取bean id
                String id = element.attributeValue("id");
                //获取bean class  全类限定名
                String aClass = element.attributeValue("class");
                //获取到类到Class对象
                Class<?> clazz = Class.forName(aClass);
                //反射创建对象
                Object o = clazz.newInstance();
                //存入map
                map.put(id, o);
            }


            //遍历 引用对象,依赖注入
            List<Element> propertyList = rootElement.selectNodes("//property");
            for (Element element : propertyList) {
                String name = element.attributeValue("name");
                String ref = element.attributeValue("ref");

                //获取父节点
                Element parent = element.getParent();
                String parentId = parent.attributeValue("id");


                Object o = map.get(parentId);
                Method[] methods = o.getClass().getMethods();
                for (Method method : methods) {
                    if (method.getName().equals("set" + name)) {
                        method.invoke(o, map.get(ref));
                    }
                }
                map.put(parentId, o);

            }

        } catch (DocumentException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    //任务二:对外提供获取实例对象的接口(根据id获取)
    public static Object getBean(String beanId) {
        return map.get(beanId);
    }


}

这样一来,我们就可以在配置文件中配置依赖关系,在代码体现中,就接声明使用对象。

那么这时候就可以改造一下service对实现类:
这时候,业务逻辑中就不用进行new一个Dao层对象出来,而是直接声明一个对象,然后提供set方法,由系统加载的时候,直接根据配置文件进行依赖注入一个对象

public class TransferServiceImpl implements TransferService {

    private BankAccountDao bankAccountDao;


    public void setBankAccountDao(BankAccountDao bankAccountDao) {
        this.bankAccountDao = bankAccountDao;
    }


    @Override
    public void transfer(String fromCardNo, String toCardNo, int money) throws SQLException {

        try {


            BankAccount from = bankAccountDao.query(fromCardNo);
            BankAccount to = bankAccountDao.query(toCardNo);

            from.setMoney(from.getMoney() - money);
            to.setMoney(to.getMoney() + money);

            bankAccountDao.update(to);
            bankAccountDao.update(from);

        } catch (Exception e) {
            e.printStackTrace();
            throw e;

        }


    }


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值