IOC容器设计学习
Spring简介:
- 以IOC与AOP为内核。分层框架。轻量级(不需要依赖其他软件,只需要JVM,容器环境)
Spring 的核心结构

每个模块对应一个Jar包。
1.4 IOC思想讲解
IOC和AOP不是Spring提出的。spring在技术上很好的把这两个思想实现
1)什么是IoC
Inversion of Control. (控制反转),这是一个技术思想。
描述的事情:Java开发领域对象创建的管理问题:
传统:A依赖B,会在A中new一个 B。
IoC思想的开发方式:不用自己new 对象了,由IoC容器帮助我们实例化对象,并且管理,我们需要使用哪个对象,去跟IoC容器要
我们丧失了创建管理对象的能力,得到了福利(不用考虑对象创建、管理和一系列事情)
控制:指的是对象创建(实例化)的权利
反转:控制权交给外部,(Spring框架,IoC容器)

2)IoC解决了什么问题
解决了对象之间的耦合问题

如果DaoImpl改了名字,则左侧两处代码都要改。
改进:

3)IoC和DI的区别
IoC和DI。
1.6 AOP编程思想
OOP思想可以解决大多数代码重复问题,但是有一些是处理不了的,假如需要加入性能监控
public class Animal {
public void eat(){
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
}
public void run(){
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
}
}
横切逻辑代码使用场景有限:事务控制、权限校验、日志打印

横切代码存在的问题:
- 横切代码重复
- 入侵业务逻辑
AOP解决,在不改变原有业务逻辑情况下,增强横切逻辑代码,避免代码重复
为什么叫面向切面编程:
原有业务代码不能动,只能操作横切逻辑代码。所以是面向横切逻辑
面:横切逻辑影响很多方法,每一个方法是一个点,组在一起是个面
1.7 Ioc与AOP问题分析
Service层需要添加事务控制,出现异常可能会导致数据错乱
1)除了new 实例化对象,还可以使用反射. Class.forName('路径')
2)使用工厂来通过反射技术生产对象,工厂模式是解耦合非常好的一种方式(工厂类解析xml,然后反射实例化对象)
xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!--跟标签beans,里面配置一个又一个的bean子标签,每一个bean子标签都代表一个类的配置-->
<beans>
<!--id标识对象,class是类的全限定类名-->
<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
<property name="ConnectionUtils" ref="connectionUtils"/>
</bean>
<bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
<!--set+ name 之后锁定到传值的set方法了,通过反射技术可以调用该方法传入对应的值-->
<property name="AccountDao" ref="accountDao"></property>
</bean>
<!--配置新增的三个Bean-->
<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>
<!--事务管理器-->
<bean id="transactionManager" class="com.lagou.edu.utils.TransactionManager">
<property name="ConnectionUtils" ref="connectionUtils"/>
</bean>
<!--代理对象工厂-->
<bean id="proxyFactory" class="com.lagou.edu.factory.ProxyFactory">
<property name="TransactionManager" ref="transactionManager"/>
</bean>
</beans>
3)单例模式(只有一个实例):
- 必须私有化构造方法,不让new
饿汉式:
package com.qcby.singleton; public class LazySingleton { private static LazySingleton instance; private LazySingleton(){} public static synchronized LazySingleton getInstance() { if(instance == null) { instance = new LazySingleton(); } return instance; } }
饿汉式:
package com.qcby.singleton; public class HungrySingleton { private HungrySingleton() {} private static final HungrySingleton instance = new HungrySingleton(); public static HungrySingleton getInstance() { return instance; } }
利用工程模式,xml配置方式创建对象
package com.lagou.edu.factory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BeanFactory {
//读取xml
//对外提供几口
private static Map<String, Object> map = new HashMap<>();
static {
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.xml");
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(inputStream);
Element root = document.getRootElement();
List<Element> elements = root.selectNodes("//bean");
for(Element bean : elements){
String id = bean.attributeValue("id");
String clazz = bean.attributeValue("class");
Class<?> aClass = Class.forName(clazz);
Object o = aClass.newInstance();
map.put(id, o);
}
//实例化完成后,维护对象的关系 有properties诉求的就有传值需求
List<Element> propertiesElements = root.selectNodes("//properties");
for(Element bean : propertiesElements) {
String name = bean.attributeValue("name");
String ref = bean.attributeValue("ref");
//找到处理当前关系的bean
Element parent = bean.getParent();
String parentId = parent.attributeValue("id");
Object po = map.get(parent.attributeValue("id"));
Method [] methods = po.getClass().getMethods();
for(Method method : methods){
if(method.getName().equalsIgnoreCase("set"+name)){
method.invoke(po, map.get(ref));
}
}
//
map.put(parentId, po);
}
} catch (DocumentException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public static Object getBean(String name){
return map.get(name);
}
}
1.10 Ioc与AOP事务控制
数据库事务归根结底是Connection 事务 connection.commit();
accountDao.updateAccountByCardNo(to); int c = 1/0; accountDao.updateAccountByCardNo(from);
两个update使用了两个connection连接。这样肯定不是一个事务控制了。(解决:两次update属于一个线程内的调用,可以给当前线程绑定一个Connection)
package com.lagou.edu.utils; import java.sql.Connection; import java.sql.SQLException; public class ConnectionUtils { private static ConnectionUtils connectionUtils = new ConnectionUtils(); public static ConnectionUtils getInstance(){ return connectionUtils; } private ThreadLocal<Connection> local = new ThreadLocal<>(); private ConnectionUtils() { } public Connection getCurrentThreadConn() throws SQLException { Connection connection = local.get(); if(connection == null) { connection = DruidUtils.getInstance().getConnection(); local.set(connection); } return connection; } }
事务控制目前在dao层,没有在service层
package com.lagou.edu.service.impl; import com.lagou.edu.utils.ConnectionUtils; import java.sql.Connection; import java.sql.SQLException; public class TransferServiceImpl { public void transfer() throws SQLException { Connection connection = ConnectionUtils.getInstance().getCurrentThreadConn(); try { //关闭自动提交事务 connection.setAutoCommit(false); //提交事务 connection.commit(); } catch (Exception e){ e.printStackTrace();; //回滚事务 connection.rollback(); } } }
1.13 使用动态代理来实现横切逻辑
1)静态代理:

每一个接口对应一个代理类 静态代理
2)动态代理
不需要对每一个业务都new一个代理类
JDK动态代理
public Object getJdkProxy(Object obj) {
// 获取代理对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try{
// 开启事务(关闭事务的自动提交)
transactionManager.beginTransaction();
result = method.invoke(obj,args);
// 提交事务
transactionManager.commit();
}catch (Exception e) {
e.printStackTrace();
// 回滚事务
transactionManager.rollback();
// 抛出异常便于上层servlet捕获
throw e;
}
return result;
}
});
}
cglib动态代理
动态代理工厂:
3)
package com.lagou.edu.proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { private ProxyFactory() { } private static ProxyFactory proxy = new ProxyFactory(); public static ProxyFactory getInstance() { return proxy; } public Object getJdkProxy(Object obj) { return Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //写增强逻辑 Object result; System.out.println("start"); result = method.invoke(obj, args); System.out.println("end"); return result; } }); } }
1.15 使用动态代理改造service事务管理
private ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory"); private TransferService transferService = (TransferService) proxyFactory.getJdkProxy(BeanFactory.getBean("transferService")) ; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置请求体的字符编码 req.setCharacterEncoding("UTF-8"); String fromCardNo = req.getParameter("fromCardNo"); String toCardNo = req.getParameter("toCardNo"); String moneyStr = req.getParameter("money"); int money = Integer.parseInt(moneyStr); Result result = new Result(); try { // 2. 调用service层方法 transferService.transfer(fromCardNo,toCardNo,money); result.setStatus("200");
2.1 IoC基础知识说明
IoC控制方式
- 纯xml
- 纯注解
- 半xml半注解
BeanFactory
- 对应不同应用和Bean创造方法有不同对应方式
- 需要自己写,才能配置相关Bean
2.4 创建Bean
- 推荐无参构建
- 静态方法(new 出来的对象加入容器进行管理)
- DI(依赖注入,可以通过容器给bean传值)
2.8 lazy-init
- 使用时候创建还是直接创建
- lazy-init 只适合singleton模式
2.9 FactoryBean
- 自定义Bean创建过程
- 可以生成某一个Bean类型的Bean实例
- 完成复杂的Bean创建

浙公网安备 33010602011771号