SpringIOC的概念理解、构造器注入、setter注入、p命名空间注入、IOC容器介绍与比较

1、IOC概念理解

  IOC(Inversion of Control)即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖,由spring来负责控制对象的生命周期和对象间的关系。

  DI(Dependency Injection)即“依赖注入”:由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。

  例如:你将需要寻找的理想中的对象(胸大、屁股大、年轻、有文化)交给婚姻中介来控制,而不是你主动去找去控制寻找,由中介为你寻找(过程你毫不知情),你选择是否接受中介为你匹配到的对象。这个过程中主动找理想对象的控制权从你到中介为:控制反转;中介输出给你的对象为:依赖注入;

(2)spring的两种Ioc容器

BeanFactory:

  BeanFactory是基础类型IOC容器。顾名思义,就是生产Bean的工厂。能够提供完整的IOC服务。没有特殊指定的话,其默认采用延迟初始化策略。只有当客户端对象需要访问容器中的某个受管对象的时候,才对该对象进行初始化和依赖注入操作。因此,相对来说,容器启动初期的时候速度是比较快的。所需要的资源有限。所以,对资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的IOC容器。

ApplicationContext:

  ApplicationContext是在BeanFactory的基础上边构建的,是相对比较高级的容器的实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他的高级特性。例如事件发布、国际化信息支持等。ApplicationContext所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。相对于BeanFactory来说,ApplicationContext会要求更多的系统资源。因为在启动时就完成了所有的初始化,容器启动的时间与BeanFactory相比会长一些。因此,ApplicationContext更适用于系统资源充足,并且要求更多功能的场景中。
   ApplicationContext间接继承自BeanFactory,所以说它是构建与BeanFactory之上的IOC容器。
比较:
   BeanFacotry是spring中比较原始的Factory。它无法支持spring的许多插件,如AOP功能、Web应用等。
   ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。
   ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,
   ApplicationContext包还提供了以下的功能:
      • MessageSource, 提供国际化的消息访问 
      • 资源访问,如URL和文件 
      • 事件传播 
      • 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的 web层  
BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。
而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。在容器启动时,我们就可以发现Spring中存在的配置错误。

(3)Spring IOC 注入方式

3.1  setter注入:

1 <bean id="helloSpring" class="com.one.ssm.impl.HelloSpring">
2         <!--此处的value的注入是通过set方法-->
3         <property name="who" value="spring"></property>
4         <property name="you" value="123456789"></property>
5     </bean>
xml书写

代码书写:

 1 public class HelloSpring {
 2     //定义who属性,值通过spring框架进行设置
 3     private String who;
 4     private String you;
 5     public void setYou(String you) {
 6         this.you = you;
 7     }
 8     public void print(){
 9         System.out.println("Hello:"+this.getWho()+"!"+you);
10     }
11     public String getWho() {
12         return who;
13     }
14     public void setWho(String who) {
15         this.who = who;
16     }
17 }
18 测试类:
19 @Test
20     public void print() throws Exception {
21         ApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring/spring-impl.xml");
22         HelloSpring helloSpring= (HelloSpring) context.getBean("helloSpring");
23         helloSpring.print();
24     }
25 结果:Hello:spring!123456789
代码

3.2   构造器注入

1   <!--构造注入实例-->
2     <bean id="math" class="com.one.ssm.impl.structorInjectionTest.MathDemo"></bean>
3     <bean id="english" class="com.one.ssm.impl.structorInjectionTest.EnglishDemo"></bean>
4     <bean id="StudyDemo" class="com.one.ssm.impl.structorInjectionTest.StudyDemo">
5         <constructor-arg ref="math"/>
6         <constructor-arg ref="english"/>
7     </bean>
构造注入xml书写

代码书写:

 1 public class EnglishDemo {
 2     public void StudyEnglish(){
 3         System.out.println("学习英语。。。。");
 4     }
 5 }
 6 
 7 
 8 public class MathDemo {
 9     public void StudyMath(){
10         System.out.println("学习数学。。。。");
11     }
12 }
13 
14 public class StudyDemo {
15     private MathDemo mathDemo;
16     private EnglishDemo englishDemo;
17 
18     //无参构造方法
19     public StudyDemo() {
20     }
21 
22     public StudyDemo(MathDemo mathDemo, EnglishDemo englishDemo) {
23         this.mathDemo = mathDemo;
24         this.englishDemo = englishDemo;
25     }
26 
27 
28     public void study() {
29         mathDemo.StudyMath();
30         englishDemo.StudyEnglish();
31     }
32 }
构造注入代码

备注:Spring通过JavaBean的无参构造函数实例化对象,当编写了带参的构造方法后,虚拟机不会再提供无参构造方法,为了保证使用,需要自行添加无参构造方法

3.3p命名空间注入

使用前添加声明:xmlns:p="http://www.springframework.org/schema/p"
xml写法:
<bean id="IocTest" class="com.one.ssm.impl.setterInjectionTest.IocTest"
p:zhangGa="三天不打鬼子,手都痒痒"
p:rod="世界上有2种人,认识2进制和不认识2进制的人"/>
语法:p:属性名="属性值"
引用:p:属性名-ref="bean的Id"

(4)注入过程子标签的使用

public class User {
    private String string;
    private List<String> list;
    private Set<String> listString;
    private Map<String,String> map;

  子标签注入:

 1 <bean id="user" class="com.one.ssm.impl.collectionPropertyInjection.User">
 2         <!--list或者数组类型的属性可以用<list>标签注入-->
 3         <property name="list">
 4             <list>
 5                 <!--定义list数组中的元素-->
 6                 <value>足球</value>
 7                 <value>篮球</value>
 8             </list>
 9         </property>
10 
11         <property name="listString">
12             <!--set类型的集合属性可以用<set>-->
13             <set>
14                 <value>足球</value>
15                 <value>篮球</value>
16             </set>
17         </property>
18 
19         <property name="map">
20             <map>
21                 <!--定义map中的键值对,如果键值对是bean对象,把value换成ref-->
22                 <entry>
23                     <key>
24                         <value>football</value>
25                     </key>
26                     <value>足球</value>
27                 </entry>
28             </map>
29         </property>
30 
31         <property name="mapString">
32             <!--Properties类型的属性用<props>,是简化了的 <map> 只能指定 String 类型的键和值-->
33             <props>
34                 <prop key="football">足球</prop>
35             </props>
36         </property>
37 
38         <!--注入空字符串-->
39         <!--<property name="string"><value></value></property>-->
40         <!--注入空值-->
41         <property name="string"><null/></property>
42     </bean>
xml书写

(5)备注:

 5.1 在子标签中有特殊符号需要转换为实体:

  <:&lt;
  >:&gt;
  &:&amp;
  ':&aops;
  ":&quot;

例如:P&G应该写成:    P&amp;G            或者使用<![CDATA[]]>形式:      <![CDATA[P&G]]>

例如:错误:<value>P&G</value>,正确:<value><![CDATA[P&G]]></value>或<value>P&amp;G</value>

加载注解定义的bean组件:<context:component-scan base-package="service,dao">   在使用注解之后,需要使用component-scan标签扫描注解标注的类,base-package指定需要扫描的基准包,多个包可以使用逗号(,)分开

5.2 使用注解实现IOC:

@Autowired:采用按照类型匹配的方式自动注入,可以省略setter方法,eg: @Autowired private UserDao dao;@Qualifier:如果有多个类型相匹配时,加入,eg: @Autowired @Qualifier("UserDao") private UserDao dao;
@Autowired:
-->对方法或者构造方法的入参就行标注
@Autowired public void setDao(@Qualifier UserDao dao){this.dao=dao}
-->对类中集合类型的成员变量进行标注
@component public class TaskQeue{@Autowired private List<Job> toDoList}:Spring会将Job类型的组件注入到toDoList
@Resource:有一个name属性值,spring解释为要注入的Bean的名称,eg:@Resource(name="userDao")private UserDao dao;
如果没有指定名称,@Resource将根据字段名或者setter方法名产生默认的名称。

5.3 spring中Bean的五个作用域:

singleton:默认值,容器中该Bean的实例只有一个
prototype:每次从容器中获取Bean时,都会创建一个新的实例,存在线程安全的组件使用
request:用于Web应用环境,针对每次HTTP请求都会创建一个实例
session:用于Web应用环境,同一个会话共享一个实例
global session:仅在porlet的Web应用中使用,同一个全局会话共享一个实例,非porlet环境,等同于session
xml配置为:
<bean id="..." class="..." scope="..."> .... </bean>
-->使用注解指定Bean的作用域
@scope("prototype")
@Service
public class UserService(){}

5.4 基于xml配置spring的自动装配

传统:
<bean id="dao" class="com.one.ssm.dao.impl.UserDaoImpl"/>
<bean id="service" class="com.one.ssm.impl.aopTest.UserServiceImpl">
<property name="userDao" ref="dao"></property></bean>


自动装配:

代替了通过property标签显示的指定Bean的依赖关系
<bean id="userMapper" class="com.one.ssm.dao.impl.UserDaoImpl"/>
<bean id="service" class="com.one.ssm.impl.aopTest.UserServiceImpl" autowire="byName"/>
备注:一般都会通过注解@Autowire来实现

以上为个人理解,仅供参考!!!

猜你喜欢

转载自www.cnblogs.com/zxh-xy/p/10700588.html