Spring学习笔记1
来源:互联网 发布:淘宝自动优化标题软件 编辑:程序博客网 时间:2024/06/16 10:15
这篇文章是为了讲解 xml 注入与注解注入的区别
预备知识:
Spring 是为了规范 IOC 开发而发布的一个框架。
IOC:即 Inverse Of Control,控制反转。将对象生成的控制权由修改不方便的源代码转变成修改相对方便的配置文件与几乎不进行修改的框架进行,这就是控制反转的原理。(书上的定义)
开始
在入门学习 Spring 的时候,举了一个例子:
interface ICustomerDao{ boolean getCustomerByAccount();}public class CustomerDao implements ICustomerDao{ @Override public boolean getCustomerByAccount(){...}}public class LoginAction{ public void execute(){ ICustomerDao icdao = new CustomerDao(); boolean b = icdao.getCustomerByAccount(); //判断 }}
我们被告知,直接在方法里 new 一个对象,是紧耦合的。
然后我们又被告知,通过增加一个工厂类来实现解耦:
public class DaoFactory{ public static ICustomerDao getCustomerDao(){ return new CustomerDao(); }}public class LoginAction{ public void execute(){ ICustomerDao icdao = DaoFactory.getCustomerDao(); boolean b = icdao.getCustomerByAccount(); //判断 }}
但是,这样一来,工厂类DaoFactroy和CustomerDao()又耦合了。并且使用这种方式的话,就得写许多静态工厂方法。
然后我们又被告知,使用反射+xml 配置文件,可以实现更好的解耦。具体实现如下:
public class BeanFactory{ public static Object getBean(String name){ //String className = xxxx(name); //上面的具体过程略过,通过参数name去读取xml文件中对应的className return Class.forName(className).newInstance(); }}
如此一来,就完全解耦了。以后要换另一个 Dao 类,只需要在配置文件里进行修改就可以了,就不需要再去修改调用 Dao 的类和工厂类了。(类名也从 DaoFactory 改成了 BeanFactory 了,因为 BeanFactory 更加通用)
记住,以上讲的只是把对象生成的控制权由修改不方便的源代码转移到了修改相对方便的配置文件。也就是控制反转。具体的说,就是将 LoginAction 类中 execute()方法中的 ICustomerDao 对象实例化的控制权从 LoginAction 类中转移到了配置文件中。
从这个层面来说,这是控制反转。
但是换一个层面,以上也可以称之为依赖注入。依赖注入,通俗地说,就是可以由配置文件决定向某个对象中存入值。这不,我们不是通过配置文件方式往 ICustomerDao 对象中注入了 CustomerDao 这个值了吗。
不过跑题了,我们这里不去细说控制反转和依赖注入是否一样。我们要讲的是 xml 注入与注解注入的区别。
xml 注入和注解注入,都是实现控制反转的一个环节。
通过使用注解来声明被修饰的那个类是一个 bean,然后在 xml 文件中使用:
<context:component-scan base-package="com.test"></context:component-scan>
来启动自动扫描,从而使得 BeanFactory 可以识别到那些被注解修饰的类,从而使得 BeanFactory 可以获取到这些 bean。
往下看应该就明白了
控制反转的核心,应该是 BeanFactory 的实现类的实例化过程,即构造函数的内容。
我们一开始使用的是配置文件的方式来实现控制反转。
那我们到底在配置文件里设置了什么?答案是我们在配置文件里注册了 bean,如:
<bean id="cat" class="com.test.Cat"> <property name="name" value="nini"></property> </bean>
这样,当我在 main 函数中,就可以通过工厂方法 getBean()方法来实例化对象了。
public static void main(String args[]){ ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Cat cat = (Cat) context.getBean("cat"); System.out.println(cat);}class Cat{ private String name; public Cat(){} //此处省去构造方法和getter方法和setter方法和toString方法}
所以,是因为在配置文件中注册了 bean,就实现了控制反转吗??不是的。关键的地方是在 BeanFactory 实现类的构造函数。
这里,ApplicationContext 是 BeanFactory 的子接口,而 ClassPathXmlApplicationContext 是一个实现类。
BeanFactory与ApplicationContext
ApplicationContext是BeanFactory的子接口,也被称为应用上下文。BeanFactory提供了Spring的配置框架和基本功能,ApplicationContext则添加了更多企业级功能(如国际化的支持),他另一重要优势在于当ApplicationContext容器初始化完成后,容器中所有的 singleton Bean 也都被实例化了,也就是说当你需要使用singleton Bean 是,在应用中无需等待就可以用,而其他BeanFactory接口的实现类,则会延迟到调用 getBean()方法时构造,ApplicationContext的初始化时间会稍长些,调用getBean()是由于Bean已经构造完毕,速度会更快。因此大部分系统都使用ApplicationContext,而只在资源较少的情况下,才考虑使用BeanFactory。
来自:https://www.cnblogs.com/zhaozihan/p/5953063.html
ClassPathXmlApplicationContext 类的实例化的过程中,通过参数 ApplicationContext.xml,找到了对应的 xml 文件,并将里面配置的 bean 全部存放到一个 HashMap 对象中。以 bean 的 id 为 key,以对应的 bean 对象为 value。然后我们才可以通过 getBean()方法,通过 id 来获取对应的 bean。
而使用注解的话,最终也是将该 bean 存到 HashMap 中。如以上的配置文件方式,转化成注解方式,则可以写成:
@Component(value="cat")class Cat{ //省略}
这里,Component注解表示将该类声明为一个 bean,而 value 的值则对应着 HashMap 的 key。然后,配合写在 xml 文件中的
<context:component-scan base-package="com.test"></context:component-scan>
即可实现 BeanFactory 在实例化的时候,自动扫描指定的包,解析那些 bean,并存到 HashMap 中。然后,就可以通过 getBean()方法实例化对象了。
重点重点重点
搞明白,控制反转的核心是 BeanFactory 的实现类的实例化过程。xml 注入与注解注入只不过是声明 bean 的方式与属性的依赖注入的方式不同。
也就是说,
xml 注入是在 xml 配置文件中注册 bean,并且在 xml 中设置 bean 与 bean 之间的引用关系(如果存在)。
而注解注入则是在源代码中通过如@Component(value=”cat”)来注册bean,通过@Autowired来实现属性的注入(即设置 bean 与 bean 之间的引用关系)。
ps:搞明白了控制反转的核心是 BeanFactroy 的实现类的实例化过程,而不是 xml注入和注解注入,就能更好的理解 xml 注入和注解注入的作用与区别了。
第一篇,逻辑衔接的不是很好,等思路清晰了,再来完善。
BeanFactory实现类实例过程的参考文章:https://www.cnblogs.com/liuling/archive/2013/04/14/BeanFactory.html
- Spring学习笔记1
- Spring学习笔记1
- spring学习笔记1
- Spring学习笔记1
- Spring学习笔记(1)
- spring学习笔记1
- spring学习笔记1
- Spring学习笔记(1)
- Spring学习笔记(1)
- Spring学习笔记(1)
- Spring学习笔记1
- spring学习笔记1
- spring学习笔记1
- Spring学习笔记1
- Spring 学习笔记 - 1
- spring学习笔记1
- Spring学习笔记1
- spring 学习笔记1
- 启动设备AR1失败,错误代码41,解决方法
- lombok的使用,简化代码又省力
- spark + psycopg2+postgre 实现insert update 功能
- 【C#】匿名函数使用
- python-open/文件操作
- Spring学习笔记1
- 一头扎进springboot之整合mybatis
- linux新建管理员用户
- Java程序员面试中的多线程问题
- 递归-无限极分类
- String、StringBuffer和StringBuilder的总结
- 数据库连接 The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone.
- 【第四届蓝桥杯】猜年龄
- android-studio Emulator: PANIC: Broken AVD system path. Check your ANDROID_SDK_ROOT value