Spring核心概念理解-IoC容器、DI、AOP
来源:互联网 发布:淘宝李宁乒乓球运动服 编辑:程序博客网 时间:2024/04/30 12:43
每个java程序员对spring的基础概念都倒背入流,AOP(面向切面编程)、IOC(控制反转)、DI(依赖注入)。今天就这几个概念做一个简单深入的原理分析。AOP\IOC主要是思想和原则性的东西。DI只是IOC原则的实现。有点类似于java中,接口和接口实现类的关系。
一、AOP
AOP(Aspect Oriented Programming) 可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。
主要功能:日志记录,性能统计,安全控制,事务处理,异常处理等等
主要意图:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码.
二、IOC和DI
在DI模式下,容器全权负责的组建的装配,容器以一些预先定义好的方式(例如setter方法或者构造函数)将匹配的资源注入到每个组件里。目前有三中类型的DI:
setter注入:
setter注入,setter注入会存在一些问题,1. 容易出现忘记调用setter方法注入组件所需要的依赖,将会导致NullPointerException异常。2. 代码会存在安全问题,第一次注入后,不能阻止再次调用setter,除非添加额外的处理工作。但是由于setter注入非常简单所以非常流行(绝大多数Java IDE都支持自动生成setter方法)。
构造器注入,构造器注入能够一定程度上解决setter注入的问题。但是该中注入方式也会带来一些问题,如果组件有很多的依赖,则构造函数的参数列表将变得冗长,会降低代码可读性。
接口注入 ,该注入方式使用的非常少,它要求组件必须实现某个接口,容器正是通过这个接口实现注入依赖的。接口注入的缺点比较明显,使用接口注入需要实现特定的接口,而接口又特定于容器,所以组件对容器产生了依赖,一旦脱离容器,组件不能重用。这是一种"侵入式"注入。
其中"setter注入"和"构造器注入"是被广泛运用的,绝大多数的IoC容器都支持这两种DI类型。
定义一个Connection 的接口:
package com.blog.blogsit.learn.spring;import javax.activation.DataSource;/** * @author hua.chen 2016年3月15日 下午11:16:05 <br> */public interface Connection { public DataSource getDataSouce();}编写两个实现类:mysql 和Oracle的实现类
package com.blog.blogsit.learn.spring;import javax.activation.DataSource;/** * @author hua.chen 2016年3月15日 下午11:16:05 <br> */public class MysqlConnection implements Connection { @Override public DataSource getDataSouce() { System.out.println("获取mysql数据源"); return null; }}编写获取连接的服务类ConnectionService
package com.blog.blogsit.learn.spring;import javax.activation.DataSource;/** * @author hua.chen 2016年3月15日 下午11:16:05 <br> */public class ConnectionService implements Connection { public Connection connection; public Connection getConnection() { return connection; } public void setConnection(Connection connection) { this.connection = connection; } @Override public DataSource getDataSouce() { return connection.getDataSouce(); }}核心实现类IocContainer
package com.blog.blogsit.learn.spring;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.util.Map;import java.util.Properties;import org.apache.commons.beanutils.PropertyUtils;import org.apache.commons.lang.ObjectUtils;import com.google.common.collect.Maps;/** * @author hua.chen 2016年3月15日 下午11:16:05 <br> */public class IocContainer { /** 内存存取 **/ private Map<String, Object> component = Maps.newHashMap(); public IocContainer() { Properties properties = new Properties(); try { properties.load(new FileInputStream( "/Users/blogsit/qunarProjects/blogsitjavabase/src/main/source/component.properties")); for (Map.Entry<Object, Object> entry : properties.entrySet()) { String key = ObjectUtils.toString(entry.getKey()); String value = ObjectUtils.toString(entry.getValue()); if (key.split("\\.").length == 1) { this.handler(key, value); } } for (Map.Entry<Object, Object> entry : properties.entrySet()) { String key = ObjectUtils.toString(entry.getKey()); String value = ObjectUtils.toString(entry.getValue()); if (key.split("\\.").length == 2) { this.handler(key, value); } } } catch (FileNotFoundException e) { System.err.println("配置文件不存在"); e.printStackTrace(); } catch (Exception e) { System.err.println("配置文件不存在"); e.printStackTrace(); } } /** * 核心类完成配置文件到对象的转化 * * @param key * @param value * @throws Exception */ private void handler(String key, String value) throws Exception { String[] parts = key.split("\\."); if (parts.length == 1) { Object object = Class.forName(value).newInstance(); this.component.put(key, object); } else if (parts.length == 2) { Object object = this.component.get(parts[0]); Object reference = this.component.get(value); // 通过setter注入 PropertyUtils.setProperty(object, parts[1], reference); } } /** * 获取相对应的对象 * * @param key * @return */ public Object getComponent(String key) { return this.component.get(key); }}编写测试类
package com.blog.blogsit.learn.spring;/** * 测试类 * * @author hua.chen 2016年3月15日 下午11:38:44 <br> */public class IocTestClient { public static void main(String[] args) { IocContainer container = new IocContainer(); Connection connection = (Connection) container.getComponent("connectionService"); connection.getDataSouce(); }}
我们看一下配置文件 component.properties
mysqlconnection=com.blog.blogsit.learn.spring.MysqlConnectionoracleconnection=com.blog.blogsit.learn.spring.OracleConnectionconnectionService=com.blog.blogsit.learn.spring.ConnectionServiceconnectionService.connection=mysqlconnection测试的输出结果:
获取mysql数据源
如果需要注入不同的类只需要修改component.properties文件。
connectionService.connection=oracleconnection
- Spring核心概念理解-IoC容器、DI、AOP
- 对spring的DI,IOC, AOP概念的理解
- Spring核心知识(IOC/DI、AOP)
- IOC/DI与AOP概念的理解
- IOC/DI与AOP概念的理解
- spring IOC AOP DI的理解
- Spring的IoC DI和AOP理解
- Spring IoC,DI,AOP的一点理解
- Spring框架IOC,DI概念理解
- Spring框架IOC,DI概念理解
- spring IOC,DI,AOP
- IoC-DI容器理解
- Spring核心 IOC DI
- Spring 核心 Ioc(DI)
- Spring ioc Di概念
- spring深入理解DIP、IOC、DI以及IOC容器
- IOC/DI与AOP概念的理解(转载及修改)
- IOC/DI与AOP概念的理解(转载及修改)
- typedef详解
- js阻塞特性
- Arcgis for js,Openlayers中加载GeoJSON
- 2015蓝桥杯试题--三羊献瑞
- 3996: [TJOI2015]线性代数|最小割
- Spring核心概念理解-IoC容器、DI、AOP
- 欢迎使用CSDN-markdown编辑器
- Android 内存优化大全(上)
- 计算两坐标的长度
- Android 内存优化大全(中)
- hw14+16
- 在Image切换时利用CrossFadeImage来产生动画特效
- pickerView使用心得,有不对的大家指正
- POJ 2676 Sudoku (DFS回溯剪枝)