前置知识
反射、注解和动态代理(引用)
github上帮助理解Spring框架的 tiny_spring 项目
tiny-spring 分析
Spring框架的核心思想
控制反转(IOC)
-
解决的问题:
将对象的创建过程交给容器来做,在使用的时候只需要去找容器要就行
-
控制反转的优点:
-
利用了在Service层用多态来接收Dao对象。即使Dao实现变换了。也不用重新编译Service代码。
- 直接在配置文件里修改
<!--配置service对象--> <bean id="userDao" class="com.lagou.dao.impl.UserDaoImpl"> </bean>
- 通过替换项目中的xxxDao实现类来实现
public class xxxServiceImpl{ @Autowired private IXXXDao xxxDao; }
- 通过容器来实现JavaBean的管理,方便程序实现。让开发者只需要关注业务代码即可。需要使用的时候只需要注入相对应的Bean。
-
-
IOC的实现方式
- IOC执行过程图示
如下图所有,可知IOC过程中的核心为BeanFactory对象和相关的配置文件
- IOC执行过程图示
-
配置文件(xxx.xml)+ 工厂模式(BeanFactory)+反射机制
-
配置文件(配置所有的Bean信息,以及相应的相互依赖信息)
将实体类之间的直接相互依赖关系,配置到配置文件中。配置文件不需要编译可以直接使用。实现个个层之间的解耦和。
<?xml version="1.0" encoding="UTF-8" ?> <beans> <!-- 配置ServiceBean id为获取的时候的标识,通过id从容器中获取Bean。 --> <!-- class 为类的全限定名,在BeanFactory中通过它来获取类对象生成实例 --> <bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl"> <!-- 在ServiceBean中需要一个accountDao 在Factory将所有的Bean创建后,进行注入操作 --> <!-- name为被引用类在引用类中的成员名称。ref为被一用对象的id --> <property name="AccountDao" ref="accountDao"></property> </bean> <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl"> </bean>
-
工厂模式加反射
public class BeanFactory{ /** * 工厂类的两个任务 * 任务一:加载解析xml,读取xml中的bean信息,通过反射技术实例化bean对象,然后放到map待用 * 任务二:提供接口方法根据id从map中获取bean(静态方法) */ // 存放所有的Bean的集合key,即为Bean的id。value 为其所对应的Bean对象。 private static Map<String,Object> map = new HashMap<>(); static{ // 读取配置文件 InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"); ... // 解析配置文件获取所有配置的bean List<Element> list = rootElement.selectNodes("//bean"); // 遍历list 开始反射生成对象。并放到map集合中 for(int i=0;i<list.size() ;i++){ String id = element.attributeValue("id"); String clazz = element.attributeValue("class"); Class<?> aClass = Class.forName(clazz); Object o = aClass.newInstance(); map.put(id,o); } // 维护bean之间的依赖关系 List<Element> list = rootElement.selectNodes("//property"); // 遍历,获取对应property的父标签获取id属性。以及property的ref和name属性 // 使用反射调用引用类的对象的Set+"name"方法。将对应的被一用Bean设置进去 } }
-
面向切面编程(AOP)
-
定义面向切面编程(Aspect-oriented programming)
-
动态代理的使用场景:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是
- 权限校验代码
- 日志代码
- 事务控制代码
- 性能监控代码。
-
底层用到的技术动态代理
- jdk 动态代理(只能代理实现了接口的对象)
- cglib动态代理(能代理所有类型的对象)
-
Spring中的声明式事物管理就是用到了AOP思想。在Service层代码执行一开始绑定一个用于整个线程的连接对象。Dao层执行的时候都从ThreadLocal中获取。从而来实现Sevice层控制事务。
Spring 中的事务传播测试