IOC注入方式

手动配置注入

测试Dao类
1
2
3
4
5
6
7
package com.example.dao;

public class UserDao {
public void test(){
System.out.println("UserDao ...");
}
}

set方法注入

注入的属性需要提供set方法。spirng2.5 以后为了简化setter方法属性注入,引入了p命名空间的概念,可以将 标签,简化为 标签的属性配置

业务类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.service;

import com.example.dao.UserDao;

public class SetIocService {
private UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void test(){
this.userDao.test();
}
}

Bean配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" class="com.example.dao.UserDao"/>

<!-- set方法注入 -->
<bean id="userService" class="com.example.service.SetIocService">
<!-- name 是UserService类的属性名称 -->
<property name="userDao" ref="userDao"/>
</bean>
</beans>

p标签需要引入命名空间:xmlns:p="http://www.springframework.org/schema/p"

p标签
1
2
3
4
5
6
7
8
9
10
11
12
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" class="com.example.dao.UserDao"/>

<!-- P标签 -->
<bean id="userServiceP" class="com.example.service.SetIocService" p:userDao-ref="userDao" />
</beans>

构造器注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.service;

import com.example.dao.UserDao;

public class ConstructorIocService {
private UserDao userDao;
public ConstructorIocService(UserDao userDao){
this.userDao = userDao;
}

public void test(){
this.userDao.test();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" class="com.example.dao.UserDao"/>

<bean id="constructorIocService" class="com.example.service.ConstructorIocService">
<!-- 构造器注入 -->
<constructor-arg name="userDao" ref="userDao"/>
</bean>
</beans>

静态工厂注入

静态工厂
1
2
3
4
5
6
7
8
9
10
11
12
package com.example.factory;

import com.example.dao.UserDao;

/**
* 静态工厂
*/
public class StaticFactory {
public static UserDao createUserDao(){
return new UserDao();
}
}
业务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.service;

import com.example.dao.UserDao;

/**
* 静态工厂注入
*/
public class StaticFactoryIocService {
private UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void test(){
this.userDao.test();
}
}
bean配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" class="com.example.dao.UserDao"/>

<!-- 静态工厂注入 -->
<bean id="staticFactory" class="com.example.factory.StaticFactory" factory-method="createUserDao"/>
<bean id="staticFactoryIocService" class="com.example.service.StaticFactoryIocService">
<property name="userDao" ref="staticFactory"/>
</bean>
</beans>

实例化工厂注入

实例化工厂
1
2
3
4
5
6
7
8
9
10
11
12
package com.example.factory;

import com.example.dao.UserDao;

/**
* 实例化工厂
*/
public class InstanceFactory {
public UserDao createUserDao(){
return new UserDao();
}
}
业务类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.service;

import com.example.dao.UserDao;

/**
* 实例化工厂注入
*/
public class InstanceFactoryIocService {
private UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void test(){
this.userDao.test();
}
}
bean 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" class="com.example.dao.UserDao"/>

<!-- 实例化工厂注入 -->
<bean id="instanceFactory" class="com.example.factory.InstanceFactory"/>
<bean id="instanceFactoryDao" factory-bean="instanceFactory" factory-method="createUserDao"/>
<bean id="instanceFactoryIocService" class="com.example.service.InstanceFactoryIocService">
<property name="userDao" ref="instanceFactoryDao"/>
</bean>
</beans>
测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.example;

import static org.junit.Assert.assertTrue;

import com.example.service.ConstructorIocService;
import com.example.service.InstanceFactoryIocService;
import com.example.service.SetIocService;
import com.example.service.StaticFactoryIocService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* Unit test for simple App.
*/
public class AppTest {

// 测试Set注入
@Test
public void TestSetIoc() {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
SetIocService service = ac.getBean("userService", SetIocService.class);
service.test();
}

// 测试构造器注入
@Test
public void TestConstructorIoc() {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
ConstructorIocService service = ac.getBean("constructorIocService", ConstructorIocService.class);
service.test();
}

// 测试静态工厂注入
@Test
public void TestStaticFactoryIoc() {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
StaticFactoryIocService service = ac.getBean("staticFactoryIocService", StaticFactoryIocService.class);
service.test();
}

// 测试实例化工厂注入
@Test
public void TestInstanceFactoryIoc() {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
InstanceFactoryIocService service = ac.getBean("instanceFactoryIocService", InstanceFactoryIocService.class);
service.test();
}
}

扫描器自动注入

bean的注入,除了使用xml配置之外,还可以使用注解配置, 配置文件需要加入命名空间 xmlns:context="http://www.springframework.org/schema/context"并开启自动注入

1
2
3
4
5
6
7
8
9
10
11
12
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--开启自动注入 -->
<context:annotation-config/>
</beans>

使用 @Resource 注解,自动注入

  • 默认根据属性字段名称查找对应的bean对象(属性字段的名称与bean标签的id属性相等)
  • 如果属性字段名称没有找到,则会通过类型(class类型)查找
  • 属性可以提供Set方法,也可以不提供Set方法
  • 注解可以声明在属性或set方法上
  • 可以设置name属性,name属性值必须与bean标签的id属性值一致;如果设置类name属性值,就只会按照name属性值查找bean对象
  • 当注入接口时,如果接口只有一个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需要被实例化的bean对象。

Dao层代码

IUserDao
1
2
3
4
5
6
7
8
package org.example.dao;

/**
* UserDao接口
*/
public interface IUserDao {
void test();
}
IUserDao Mysql 实现类
1
2
3
4
5
6
7
8
package org.example.dao;

public class UserDaoMySqlImpl implements IUserDao{
@Override
public void test() {
System.out.println("UserDao Mysql ...");
}
}
IUserDao Oracle 实现类
1
2
3
4
5
6
7
8
package org.example.dao;

public class UserDaoOracleImpl implements IUserDao{
@Override
public void test() {
System.out.println("UserDao Oracle ...");
}
}

Service层代码

接口
1
2
3
4
5
package org.example.service;

public interface IUserService {
void test();
}
实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.example.service;

import org.example.dao.IUserDao;

import javax.annotation.Resource;

public class UserServiceImpl implements IUserService{
@Resource(name="userDaoMysql")
private IUserDao userDao;

@Override
public void test() {
this.userDao.test();
System.out.println("UserService ...");
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package org.example;

import static org.junit.Assert.assertTrue;

import org.example.service.IUserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* Unit test for simple App.
*/
public class AppTest
{
@Test
public void TestUserService(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
IUserService service = ac.getBean("userService", IUserService.class);
service.test();
}
}

Bean配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--开启自动注入 -->
<context:annotation-config/>

<!-- dao -->
<bean id="userDaoMysql" class="org.example.dao.UserDaoMySqlImpl"/>
<bean id="userDaoOracle" class="org.example.dao.UserDaoOracleImpl"/>

<!-- service -->
<bean id="userService" class="org.example.service.UserServiceImpl"/>
</beans>

使用 @Autowired 注解自动注入

@Autowired 注解使用方法和 @Resource 注解基本一样

  • 默认通过类型(Class类型)查找Bean对象,与属性字段的名称无关
  • 属性可以提供set方法,也可以不提供Set方法
  • 注解可以声明在属性级别或set方法级别
  • 可以添加 @Qualifier 结合使用,通过value属性值查找Bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)

Ioc扫描器

bean对象统一进行管理,简化开发配置,提高开发效率。

首先Spring配置文件需要开启扫描,指定配置范围

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!-- 开启扫描,配置扫描范围 -->
<context:component-scan base-package="org.example"/>

</beans>

使用指定的注解(声明在类级别),bean对象的id属性默认是类名首字母小写

  • Dao层:@Repository
  • Servicece层:@Service
  • Controller层:@Controller
  • 任意层:@Component

如下面的代码

Dao数据访问层
1
2
3
4
5
6
7
8
9
10
11
package org.example.dao;

import org.springframework.stereotype.Repository;

@Repository
public class AuthDao {
public void test (){
System.out.println("AutoDao ...");
}
}

Service业务服务层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.example.service;

import org.example.dao.AuthDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AuthService {
@Autowired
private AuthDao authDao;

public void test(){
this.authDao.test();
System.out.println("Auth service ...");
}
}
控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.example.controller;

import org.example.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class AuthController {
@Autowired
private AuthService authService;

public void test(){
this.authService.test();
System.out.println("Auth Controller ...");
}
}
测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.example;

import static org.junit.Assert.assertTrue;

import org.example.controller.AuthController;
import org.example.service.IUserService;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* Unit test for simple App.
*/
public class AppTest
{
@Test
public void TesIocScan(){
BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
AuthController authController = factory.getBean("authController", AuthController.class);
authController.test();
}
}