IoC

什么是IoC?

IoC是Inversion of Control(控制反转)的简称,注意它是一个技术思想。描述的是对象创建、管理的事情。

控制反转就是说将对象创建、管理的权力交给了外部环境(IoC容器)。

IoC的作用:解决了对象之间的耦合问题。

什么是DI?

DI是Dependancy Injection(依赖注入)的简称,指容器会把对象依赖的其他对象注入。比如A对象里声明了一个B的属性,那么就需要容器把B对象注入给A。

什么是AOP?

AOP是 Aspect oriented Programming(⾯向切⾯编程)的简称。

ioc的三种实现机制(教你手撸一个IOC容器)(1)

在上面的代码中,多个方法都出现了相同的代码(可以称之为横切逻辑代码)。这部分代码不仅重复,而且跟业务逻辑没有关系但是混杂在一起。这时AOP出现了,它提供了横向抽取机制,将这部分横切代码和业务逻辑代码分开。

ioc的三种实现机制(教你手撸一个IOC容器)(2)

AOP的作用:在不改变原有业务逻辑的情况下,增强横切逻辑代码,解耦合。

手写IOC

首先我们看一下在没有Spring之前,我们是怎么开发一个web程序的呢?

ioc的三种实现机制(教你手撸一个IOC容器)(3)

那么针对上面的两个问题,我们如何进行解决呢?

综上,我们可以用工厂模式 反射技术把对象都实例化好,放在一个map里面,如果需要某个对象,就可以直接从这个map里面取。

除此之外,我们还需要一个xml文件,里面来定义对象的全类名(反射需要),如果有依赖,还需要定义类与类之间的依赖关系。

<beans> <bean id="accountDao" class="com.mmc.ioc.dao.impl.AccountDaoImpl"></bean> <bean id="transferService" class="com.mmc.ioc.service.impl.TransferServiceImpl"> <!--这里的name默认为set name就是方法名--> <property name="AccountDao" ref="accountDao"></property> </bean> </beans>

核心代码:

public class beanFactory { private static Map<String,Object> beanMap=new HashMap<>(); static { InputStream inputStream=BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"); SAXReader SAXReader=new SAXReader(); try { Document document = saxReader.read(inputStream); Element rootElement = document.getRootElement(); List<Element> beans = rootElement.selectNodes("//bean"); for (Element element:beans){ String id = element.attributeValue("id"); String clazz = element.attributeValue("class"); Object instance = Class.forName(clazz).newInstance(); beanMap.put(id,instance); } //实例完后填充对象的依赖 List<Element> propertys = rootElement.selectNodes("//property"); for (Element element:propertys){ String name = element.attributeValue("name"); String ref = element.attributeValue("ref"); Element parent = element.getParent(); String parentId = parent.attributeValue("id"); Object instance = beanMap.get(parentId); Object refInstance = beanMap.get(ref); Method setMethod = instance.getClass().getDeclaredMethod("set" name,refInstance.getClass().getInterfaces()); setMethod.invoke(instance,beanMap.get(ref)); } } catch (Exception e) { e.printStackTrace(); } } public static Object getBean(String name){ return beanMap.get(name); } }

那么接下来我们想要使用对象的时候,就不用new了,而是从beanFactory里面去拿。

这样一个简易的AOP就完成了。

手写AOP实现

我们解决了上面的问题1,那么问题2事务控制如何解决呢?

分析:数据库事务归根结底是Connection的事务,connection.commit()提交事务,connection.rollback()回滚事务。

改造完成:

@Override public void transfer(String fromCardNo, String toCardNo, int money) throws Exception { //关闭自动提交 connectionUtils.getThreadConn().setAutoCommit(false); try { Account from = accountDao.queryAccountByCardNo(fromCardNo); Account to = accountDao.queryAccountByCardNo(toCardNo); from.setMoney(from.getMoney()-money); to.setMoney(to.getMoney() money); accountDao.updateAccountByCardNo(to); int i=10/0; accountDao.updateAccountByCardNo(from); //提交事务 connectionUtils.getThreadConn().commit(); } catch (Exception e) { //回滚事务 connectionUtils.getThreadConn().rollback(); throw e; } }

在两次update语句中间手动加了个异常,可以发现数据库两条数据都没变,说明事务控制成功。

但是如果多个方法都需要加事务控制的话,我们需要给多个方法加上下面这一套重复的代码

connectionUtils.getThreadConn().setAutoCommit(false); try { //省略部分代码 // ----- //提交事务 connectionUtils.getThreadConn().commit(); } catch (Exception e) { //回滚事务 connectionUtils.getThreadConn().rollback(); throw e; }

怎么解决呢?我们可以通过代理模式给每个方法代理

代码如下:

public class ProxyFactory { private ConnectionUtils connectionUtils; public void setConnectionUtils(ConnectionUtils connectionUtils) { this.connectionUtils = connectionUtils; } public Object getJdkProxy(Object object){ return Proxy.newProxyInstance(ProxyFactory.class.getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //关闭自动提交 connectionUtils.getThreadConn().setAutoCommit(false); Object result; try { result= method.invoke(object,args); //提交事务 connectionUtils.getThreadConn().commit(); } catch (Exception e) { //回滚事务 connectionUtils.getThreadConn().rollback(); throw e; } return result; } }); } }

每个需要加事务的对象,只要调用getJdkProxy方法获取到代理对象,再使用代理对象执行方法,就能实现事务控制了。使用方法如下:

private ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory"); private TransferService transferService= (TransferService) proxyFactory.getJdkProxy(BeanFactory.getBean("transferService"));

这样就相当于把横切逻辑代码提取出来了,如果把这套机制抽出来就是AOP的实现了。

原文链接:https://www.cnblogs.com/javammc/p/15538365.html

,