核心
- IOC的核心思想:将类对象的创建交给Spring来管理,然后通过Spring提供的相应方式来进行使用
- IOC的具体实现:根据核心思想的体现,第一步我们要将类对象的创建交给Spring来管理:导入相关jar包,然后每新建一个类就通过xml或者注解的方式将其注册到Spring容器中(包括DI),这样所有bean对象的创建都交给Spring来管理。第二步通过Spring提供的相应方式来进行使用:以前通过new使用,现在我们通过创建一个对象工厂例如ApplicationContext(初始化工厂时会根据applicationContext.xml配置文件实例化所有xml或者注解方式注册的bean对象),然后使用工厂的getBean方法,通过参数指定要获取的某个bean对象即可使用!后期进行框架整合后只需在配置文件中进行配置即可。
基础
1.为什么要学习Spring
开始编程通常只有实现类,后来我们开始面向接口编程,这是多态的表现。但是此时接口和实现类还有耦合(联系过紧),当切换底层实现类,往往需要修改源代码,然后出现了工厂模式+反射机制+配置文件对其进行了解耦合处理,这就是Spring框架的底层实现,学习Spring更多的是学习这种编程思想!
2.Spring的两个核心概念
- IOC:控制反转,将对象的创建权反转给了Spring,使其在配置文件中进行对象的创建和管理,不需要我们再在程序中通过关键字new进行创建
- DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来
3.scope:Bean的作用范围
- singleton:默认的,Spring会采用单例模式仅创建一个bean对象【常用】
- prototype:在对Bean定义的多次访问中,创建的是多个不同的Bean实例,等价于Java中的new操作符,属于多例模式。【Struts2和Spring整合一定会使用】
- request:应用在web项目中,Spring创建这个类以后,将这个类存入到request域中
- session:应用在web项目中,Spring创建这个类以后,将这个类存入到session域中
- globalSession:应用在web项目中,必须在porlet环境下使用
4.为什么要进行IOC的注解开发?
当需要对bean对象的创建交给Spring来管理时,默认情况下我们每创建一个类都需要在配置文件中对其进行注册加载到Spring容器中,这样Spring才能对其进行管理。但是实际开发会创建很多个类,使用这种方式加载就显得很笨重,所以就出现了IOC注解的方式,通过配置IOC的注解可以自动扫描所有包下的所有类进行自动注册!和xml中的手动配置本质是相同的,但是却可以提高开发效率!
5.Spring的IOC注解开发详解【注解后的括号内可以指定类的bean名称或者属性的value值】
前提:使用注解开发首先应该在配置文件中对相关包下的类经行组件扫描,否则类无法加载到Spring容器中进行管理!
例如:<context:component-scan base-package="com.cyn.spring">
</context:component-scan>
(1)@Component:组件-修饰一个类,表明将这个类的创建交给Spring来管理
注意:这个注解还有三个衍生注解(功能类似)
- @Controller:web层
- @Service:service层
- @Repository:dao层
(2)属性注入的注解(类的方法中可以不提供set方法!)
- @value:设置普通属性的值
- @Autowired:设置对象类型的属性的值,默认按照类型完成属性注入。但是我们习惯按照名称完成属性注入,所以必须让@Autowired注解和@Qualifier一起使用完成按照名称的属性注入
- @Resource:完成对象类型的属性的注入,按照名称完成的属性注入,可以代替@Autowired注解和@Qualifier【实际开发中使用】
(3)生命周期的注解
- @PostConstruct:初始化方法
- @PreDestroy:销毁方法
(4)Bean作用域范围的注解
- @scope:作用范围,值的范围和上述一致!
细节
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"):
- 注意:ApplicationContext是工厂接口,而ClassPathXmlApplicationContext才是真正的工厂实现类,当执行此方法的时候就会实例化配置文件中所有的bean对象。如果某个bean对象配置了相对应的初始化方法,那么实例化的过程中就会调用该方法对bean对象进行实例化!【在框架整合后,只需要在配置文件中进行配置即可实例化spring容器】
- 当使用@Autowired注解设置对象类型的属性的值的时候,默认是按照类型完成属性注入,即它会在spring容器中寻找与其类型相匹配的类进行属性注入,不管这个类的id名是否与属性名一致,与xml的属性注入不同。
- 如果在注解类的时候不指定具体的id名,那么默认情况下,Bean的名称派生自简单的类名但首字符为小写。
- xml和注解的比较
- XML:可以适用任何场景,结构清晰,维护方便
- 注解:有些地方用不了,当这个类不是自己提供的而是源码则无法使用注解,但是开发方便
6.组件扫描是扫描类上的注解!在不使用扫描的时候,我们可以在配置文件中通过<context:annotation-config/>来开启属性注入的注解,而对于类的注册通过xml配置!
7.如果在xml文件中配置了相关约束却没有提示,记得在eclipse下进行配置!
8.通过xml方式进行依赖注入的前提是类中必须提供set方法,而使用注解进行依赖注入则没有要求!
- 注解方式依赖注入
- 等价于xml方式:<property name="jdbcTemplate" ref="jdbcTemplate"/>
- 等价于java方式:JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource)
- 等价于工厂的JdbcTemplate jdbcTemplate=applicationContext.getBean("jdbcTemplate")
附录一:基于xml方式的IOC配置文件
项目地址:
- applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Spring的入门配置 -->
<bean id = "userDao" class="com.cyn.spring.demo1.UserMybatisDaoImpl">
<property name="name" value="张三"></property>
</bean>
<!-- Spring的Bean的生命周期的配置 -->
<!--
init-method:Bean被初始化时候执行的方法
destroy-method:Bean被销毁时候执行的方法(工厂关闭)
scope:Bean的作用域范围
-->
<bean id = "customerDao" class = "com.cyn.spring.demo2.CustomerDaoImpl" init-method="setup" destroy-method="destroy"
scope="singleton">
</bean>
<!-- Spring的属性注入的方式 -->
<!-- 1.构造方法注入 -->
<bean id = "car" class = "com.cyn.spring.demo4.Car">
<constructor-arg name="name" value="宝马"/>
<constructor-arg name="price" value="520"/>
</bean>
<!-- 2.1setter方法注入基本类型的属性 -->
<bean id = "car2" class = "com.cyn.spring.demo4.Car2">
<property name="name" value="奔驰"/>
<property name="price" value="1314"/>
</bean>
<!-- 2.1.1改为p名称空间的方式 -->
<!--
<bean id = "car2" class = "com.cyn.spring.demo4.Car2" p:name="奔驰" p:price="1314"/>
-->
<!-- 2.2setter方法注入对象类型的属性 -->
<bean id = "employee" class = "com.cyn.spring.demo4.Employee">
<!--
value:设置普通类型的值
ref:设置其他类型的id或name
-->
<property name="name" value="张三"/>
<property name="car2" ref="car2"/>
</bean>
<!-- 2.2.2改为p名称空间方式的属性注入 -->
<!--
<bean id = "employee" class = "com.cyn.spring.demo4.Employee" p:name="李四" p:car2-ref="car2"/>
-->
<!-- 2.2.3改为SpEL方式的属性注入 -->
<!--
<bean id = "employee" class = "com.cyn.spring.demo4.Employee">
<property name="name" value="#{'李四'}"/>
<property name="car2" value="#{car2}"/>
</bean>
-->
<!-- 2.3setter方法注入集合类型的属性 -->
<bean id = "collectionBean" class = "com.cyn.spring.demo5.CollectionBean">
<!-- 2.3.1注入数组类型 -->
<property name="arrs">
<list>
<value>张三</value>
<value>李四</value>
<value>赵五</value>
</list>
</property>
<!-- 2.3.2注入List集合 -->
<property name="list">
<list>
<value>小明</value>
<value>小红</value>
<value>小李</value>
</list>
</property>
<!-- 2.3.3注入set集合 -->
<property name="set">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 2.3.4注入Map集合 -->
<property name="map">
<map>
<entry key="aaa" value="111"/>
<entry key="bbb" value="222"/>
<entry key="ccc" value="333"/>
</map>
</property>
</bean>
</beans>
附录二:基于注解方式的IOC配置文件
项目地址:
- applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Spring的IOC的注解的入门 -->
<!-- 使用IOC的注解开发,配置组件扫描(哪些包下的哪些类使用IOC注解) -->
<context:component-scan base-package="com.cyn.spring">
</context:component-scan>
<!-- 在没有扫描的情况下,使用属性注入的注解:@Resource、@value、@Autowired... -->
<!--
<context:annotation-config/>
-->
<!-- 在这里对类进行xml方式的注册 -->
</beans>