Spring IOC 几种方式 总结

Spring框架是目前各大Java开发者追捧的框架之一,相信对于大家来说并不陌生,Spring之所以这么流行,少不了他的两大核心技术IOC和IOP。我们这里重点讲述Spring框架的IOC技术。在我们平 常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一 管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。 依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序 员来做而是交给spring容器来做。

在Spring容器中为一个bean配置依赖注入有三种方式:

1) 使用属性的setter方法注入  这是最常用的方式;

2) 使用构造器注入;

3) 使用Filed注入(用于注解方式)

准备工作

Spring是开源框架,在开始我们的实例之前,需要IOC必备的开发包。

1.使用属性的setter方法注入

首先要配置被注入的bean,在该bean对应的类中,应该有要注入的对象属性或者基本数据类型的属性,并且拥该属性或数据类型的set方法。

 1 //我们首先定义一个UserDao的接口
 2 interface UserDao {
 3
 4     public void say();
 5 }
 6
 7
 8 //定义一个类,并且实现我们的UserDao接口
 9 class UserDaoImpl implements UserDao {
10
11     @Override
12     public void say() {
13         System.out.println("我是UserDaoImpl类,我是实现了UserDao接口,我是通过set方法创建的。");
14     }
15 }
16
17
18 class UserService {
19
20     //注意这里定义的userDao是接口的引用。当然也可以是 UserDaoImpl userDao 。
21     //我们提倡用前者,面向接口编程,来降低我们代码的耦合度!!!
22     private UserDao userDao;
23
24     public void setUserDao(UserDao userDAO) {
25         this.userDao = userDAO;
26     }
27
28     public void fun() {
29
30         System.out.println("我要执行真正的逻辑操作了");
31
32         //请注意,在整个过程中,我们并没有手动实例化过userDao对象,而是让Spring容器为我们实例化的
33         userDao.say();
34     }
35 }
36
37
38 public class SetTest {
39
40     public static void main(String[] args) {
41         ApplicationContext context = new ClassPathXmlApplicationContext("set.xml");
42
43         // 2、从容器中获取Bean
44         UserService userDao = context.getBean("userService", UserService.class);
45
46         // 3、执行业务逻辑
47         userDao.fun();
48     }
49 }

下面我们来看一下我们的set.xml是如何配置的

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 4     xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 7         http://www.springframework.org/schema/context
 8         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 9
10     <bean id="userService" class="UserService">
11           <!--依赖注入,配置当前类中相应的属性,该属性必须有对应的set方法-->
12         <property name="userDao" ref="userDao"></property>
13     </bean>
14     <bean id="userDao" class="UserDaoImpl"></bean>
15
16 </beans>

不知道你对上述配置文件是否了解,我们就先简单的介绍一下,<bean>代表一个java对象,id="userService" class="UserService"  ,则相当于我们平时写Java代码的UserService userService 。<property>则是为配置的对象设置属性。<property name="userDao" ref="userDao"></property> 在这个标签中 name 代表着 class="UserService"  这个类的属性,ref 则是指向已经当经定义好的bean对象。请特别留意代码中的那句注释“<!--依赖注入,配置当前类中相应的属性,该属性必须有对应的set方法-->”,否则运行时会报错。特别注意了哦!! 在这里我们的class引入的是类的路径: 包名.类型 ,例如在 在com包下有类 Test,则class = "com.Test" 。特别注意了哦。

有时候,我们希望产生对象是通过我们写工厂方法产生,并且又希望能通过Spring来产生对象。

1.1静态工厂注入的处理

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,

而是依然通过Spring注入的形式获取。

下面我们来看一个这样的例子

 1 //我们首先定义一个UserDao的接口
 2 interface UserDao {
 3
 4     public void say();
 5 }
 6
 7 //定义一个类,并且实现我们的UserDao接口
 8 class UserDaoImpl implements UserDao {
 9
10     @Override
11     public void say() {
12         System.out.println("我是UserDaoImpl类,我是实现了UserDao接口,我是通过工厂的静态方法产生的");
13     }
14 }
15
16 //添加静态工厂
17 class DaoFactory {
18     //静态工厂
19     public static final UserDao getStaticFactoryDaoImpl(){
20         return new UserDaoImpl();
21     }
22 }
23
24 class UserService {
25
26     private UserDao userDao;
27
28     public void setUserDao(UserDao userDao) {
29         this.userDao = userDao;
30     }
31
32     public void fun() {
33         userDao.say();
34     }
35 }
36
37 public class FactoryStaticsTest {
38
39     public static void main(String[] args) {
40
41         ApplicationContext context = new ClassPathXmlApplicationContext("factory.statics.xml");
42
43         // 2、从容器中获取Bean
44         UserService userDao = context.getBean("userService", UserService.class);
45
46         // 3、执行业务逻辑
47         userDao.fun();
48     }
49
50 }

我们看一下 factory.statics.xml配置文件的配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 4     xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 7         http://www.springframework.org/schema/context
 8         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 9
10     <bean id="userService" class="factory.statics.UserService">
11           <!--依赖注入,配置当前类中相应的属性,该属性必须有对应的set方法-->
12         <property name="userDao" ref="userDao"></property>
13     </bean>
14     <bean id="userDao" class="factory.statics.DaoFactory"
15     factory-method="getStaticFactoryDaoImpl"></bean>
16 </beans>

1.2 实例工厂的方法注入

实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法。(PS: 先有工厂对象,在通过工厂的对象来产生我们的业务逻辑对象。)

 1 //我们首先定义一个UserDao的接口
 2 interface UserDao {
 3
 4     public void say();
 5 }
 6
 7 //定义一个类,并且实现我们的UserDao接口
 8 class UserDaoImpl implements UserDao {
 9     @Override
10     public void say() {
11         System.out.println("我是UserDaoImpl类,我是实现了UserDao接口,我是通过工厂的实例方法产生的");
12     }
13 }
14
15 //添加工厂类
16 class DaoFactory {
17
18     //产生UserDao对象
19     public  UserDao getFactoryDaoImpl(){
20         return new UserDaoImpl();
21     }
22 }
23
24 class UserService {
25
26     private UserDao userDao;
27
28     public void setUserDao(UserDao userDao) {
29         this.userDao = userDao;
30     }
31
32     public void fun() {
33         userDao.say();
34     }
35 }
36
37 public class FactoryObject {
38
39     public static void main(String[] args) {
40         ApplicationContext context = new ClassPathXmlApplicationContext("factory.object.xml");
41
42         // 2、从容器中获取Bean
43         UserService userDao = context.getBean("userService", UserService.class);
44
45         // 3、执行业务逻辑
46         userDao.fun();
47     }
48 }

下面我们来看一下 factory.object.xml  配置文件的配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 4     xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 7         http://www.springframework.org/schema/context
 8         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 9
10     <bean id="userService" class="factory.object.UserService">
11           <!--依赖注入,配置当前类中相应的属性,该属性必须有对应的set方法-->
12         <property name="userDao" ref="userDao"></property>
13     </bean>
14     <bean id="daoFactory" class="factory.object.DaoFactory"></bean>
15     <bean id="userDao" factory-bean="daoFactory"
16     factory-method="getFactoryDaoImpl"> </bean>
17 </beans>

2.使用构造器注入

使用构造器注入方式,不用为该类的属性属性设置setter方法,但是需要生成该类的相应的构造方法构造方法。

 1 //我们首先定义一个UserDao的接口
 2 interface UserDao {
 3
 4     public void say();
 5 }
 6
 7 //定义一个类,并且实现我们的UserDao接口
 8 class UserDaoImpl implements UserDao {
 9     @Override
10     public void say() {
11         System.out.println("我是UserDaoImpl类,我是实现了UserDao接口,我是通过构造方法创建的。");
12     }
13 }
14
15 class UserService {
16
17     private UserDao userDao;
18
19     public UserService(UserDao userDao){
20         this.userDao = userDao;
21     }
22
23     public void fun() {
24         userDao.say();
25     }
26 }
27
28
29 public class ConstructorTest {
30
31     public static void main(String[] args) {
32
33         ApplicationContext context = new ClassPathXmlApplicationContext("construct.xml");
34
35         // 2、从容器中获取Bean
36         UserService userDao = context.getBean("userService", UserService.class);
37
38         // 3、执行业务逻辑
39         userDao.fun();
40     }
41
42 }

下面我们看一下 construct.xml 配置文件是怎么写的

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xsi:schemaLocation="
 6         http://www.springframework.org/schema/beans
 7         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 8         http://www.springframework.org/schema/context
 9         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
10
11     <bean id="userService" class="constructor.UserService">
12         <!--创建构造器注入,如果主类有带参的构造方法则需添加此配置 -->
13         <constructor-arg index="0" ref="userDao"></constructor-arg>
14     </bean>
15     <bean name="userDao" class="constructor.UserDaoImpl"></bean>
16 </beans>

3.使用字段(Filed)注入(用注解方式)

在Spring中,注入依赖对象可以采用手工装配或自动装配,在实际应用开发中建议使用手工装配,因为自动装配会产生许多未知情况,开发人员无法预见最终的装配结果。

手工装配依赖对象又分为两种方式:

一种是在XML文件中,通过在bean节点下配置;如上面讲到的使用属性的setter方法注入依赖对象和使用构造器方法注入依赖对象都是这种方式。

另一种就是在java代码中使用注解的方式进行装配,在代码中加入@Resource或者@Autowired

怎样使用注解的方式来为某个bena注入依赖对象呢?

首先,我们需要在Spring容器的配置文件applicationContext.Xml文件中配置以下信息,该信心是一个Spring配置文件的模板:

<?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:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd

">

</beans>

注意:只有配置了红色部分的代码 才可以引入注解的命名空间,否则报错。  以上的配置隐式的注册了多个对注释进行解析的处理 器:AutowiredAnnotationBeanPostProcessor、 CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 等。

其次,在配置文件中打开<context:annotation-config>节点,告诉Spring容器可以用注解的方式注入依赖对象;其在配置文件中的代码如下:

<beans>

……

<context:annotation-config></context:annotation-config>

……

</beans>

第三,在配置文件中配置bean对象,如下:

<bean id="userDao" class="annotation.manul.UserDaoImpl"></bean>
   <bean id="userService" class="annotation.manul.UserService"></bean>

下面我们来看一个注解注入的例子

 1 interface UserDao {
 2
 3     void say();
 4 }
 5
 6
 7 class UserDaoImpl implements UserDao {
 8     @Override
 9     public void say() {
10         System.out.println("I am created by manual annotation! + UserDaoImpl");
11     }
12 }
13
14 class UserDaoImplEx implements UserDao {
15
16     @Override
17     public void say() {
18         System.out.println("I am created by manual annotation! + UserDaoImplEx!!!!!");
19     }
20 }
21
22 class UserService {
23
24     @Resource(name="userDao")
25     private UserDao userDao = null;
26
27     public UserDao getUserDao() {
28         return userDao;
29     }
30
31     //在该属性的set方法上添加对应的方法,也能达到相同的效果。
32     /*@Resource(name="userDao")
33     public void setUserDa(UserDao userDao) {
34         this.userDao = userDao;
35     }*/
36
37     public void fun() {
38         userDao.say();
39     }
40 }
41
42 public class AnnotationManulTest {
43
44     public static void main(String[] args) {
45
46         ApplicationContext context = new ClassPathXmlApplicationContext(
47                 "applicationContext.xml");
48
49         // 2、从容器中获取Bean
50
51         UserService userDao = context.getBean("userService", UserService.class);
52
53         // 3、执行业务逻辑
54         userDao.fun();
55
56     }
57
58 }

下面我们来看一下applicationContext.xml文件的配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 4     xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans
 6         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 7         http://www.springframework.org/schema/context
 8         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 9     <!-- 打开<context:annotation-config>节点,告诉Spring容器可以用注解的方式注入依赖对象 -->
10     <context:annotation-config></context:annotation-config>
11     <context:component-scan base-package="annotation.manul" />
12
13     <!-- <bean id="userDaoEx" class="annotation.manul.UserDaoImplEx"></bean>
14     <bean id="userDao" class="annotation.manul.UserDaoImpl"></bean>
15     <bean id="userService" class="annotation.manul.UserService"></bean> -->
16
17 </beans>

其中,在Java代码中可以使用@Autowired或@Resource注解方式进行Spring的依赖注入。两者的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。

比如:我们用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与UserDAO对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;

如果用@Resource进行依赖注入,它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型,例如:@Resource(name="userDao"),如果没有找到该名称,则会按照类型去寻找,找到之后,会对字段userDao进行注入。

通常我们使用@Resource。

使用注解注入依赖对象不用再在代码中写依赖对象的setter方法或者该类的构造方法,并且不用再配置文件中配置大量的依赖对象,使代码更加简洁,清晰,易于维护。

在Spring IOC编程的实际开发中推荐使用注解的方式进行依赖注入。

依赖注入—自动装配

Spring中提供了自动装配依赖对象的机制,但是在实际应用中并不推荐使用自动装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。

自动装配是在配置文件中实现的,如下:

<bean id="***" class="***" autowire="byType">

只需要配置一个autowire属性即可完成自动装配,不用再配置文件中写<property>,但是在类中还是要生成依赖对象的setter方法。

Autowire的属性值有如下几个:

· byType 按类型装配  可以根据属性类型,在容器中寻找该类型匹配的bean,如有多个,则会抛出异常,如果没有找到,则属性值为null;

· byName 按名称装配  可以根据属性的名称在容器中查询与该属性名称相同的bean,如果没有找到,则属性值为null;

· constructor 与byType方式相似,不同之处在与它应用于构造器参数,如果在容器中没有找到与构造器参数类型一致的bean,那么将抛出异常;

· autodetect 通过bean类的自省机制(introspection)来决定是使用constructor还是byType的方式进行自动装配。如果发现默认的构造器,那么将使用byType的方式。

时间: 2024-12-20 01:31:55

Spring IOC 几种方式 总结的相关文章

spring ioc三种注入方式

spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容器控制程序之间的关系,而不是由代码直接控制 由于控制权由代码转向了容器,所以称为反转 接口注入 Setter 注入 构造器注入 三种依赖注入方式的比较 : 接口注入: 接口注入模式因为历史较为悠久,在很多容器中都已经得到应用.但由于其在灵活性.易用性上不如其他两种注入模式,因而在 IOC 的专题世界

关于整合spring+mybatis 第二种方式

和第一种方式一样的步骤,不过bean.xml中有些许差异 <!-- 配置sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property&g

Spring IOC的注入方式

Spring IOC注入的方法主要有两种 1:设值注入 2:构造注入 简单来说一个是调用set方法设值,一个是通过构造函数设值 Spring-ioc.xml <?xml version= "1.0" encoding= "UTF-8"?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2

ActiveMQ(06):ActiveMQ结合Spring开发--第二种方式

一.pom.xml与mq.properties Spring提供了对JMS的支持,需要添加Spring支持jms的包,如下: <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-jms</artifactId>     <version>4.1.7.RELEASE</version> </dependency&g

spring ioc的实现方式

1.编写用来获取数据的接口 public interface DataBase{ //改方法用来获取数据 public void getData(); } 2.编写具体负责获取数据的类 public class SqlDataBase1 implement DataBase{ //该方法1用来获取数据 public void getData(){ //以下是具体获取数据的代码 } } public class SqlDataBase2 implement DataBase{ //该方法2用来获取

Spring IOC的三种注入方式

Spring IOC三种注入方式: 1.    接口注入 2.    getter,setter方式注入 3.    构造器注入 对象与对象之间的关系可以简单的理解为对象之间的依赖关系:A类需要B类的一个实例来进行某些操作,比如在A类的方法中需要调用B类的方法来完成功能,叫做A类依赖于B类.控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术,由容器控制程序之间的关系,而不是由代码直接控制. 1.接口注入 public class ClassA {  private InterfaceB

Spring 实例化Bean的两种方式

使用Spring管理Bean也称依赖注入( Dependency Injection, DI ),通过这种方式将Bean的控制权交给Spring 在使用Spring实例化一个对象时,无论类是否有参数都会默认调用对象类的无参构造,对于有参数的情况,Spring有两种方式可以带参实例化 示例类 Shape public class Shape { private Integer width; private Integer height; public Shape() { System.out.pr

Spring学习(二)spring ioc注入的三种方式

一.spring ioc注入有哪三种方式: a setter 原理 : 在目标对象中,定义需要注入的依赖对象对应的属性和setter方法:"让ioc容器调用该setter方法",将ioc容器实例化的依赖对象通过setter注入给目标对象,封装在目标对象的属性中. b 构造器 原理 : 为目标对象提供一个构造方法,在构造方法中添加一个依赖对象对应的参数.ioc容器解析时,实例化目标对象时会自动调用构造方法,ioc只需要为构造器中的参数进行赋值:将ioc实例化的依赖对象作为构造器的参数传入

【SSH系列】深入浅出spring IOC中三种依赖注入方式

spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,小编的脑袋中全是大大的问号,不过没有关系,今天这篇博文,小编主要来简单的介绍一下在spring IOC中依赖注入的方法. 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性.我们可以从以下几个方面理解: a.参与者都