本教程源码请访问:tutorial_demo
在学习基于注解的IOC和DI之前,大家要有一个基本的认识,即注解配置和之前学习的XML配置要实现的功能是一样的,都是为了降低程序间的耦合,只是配置的形式不一样。
一、使用注解实现IOC
1.1、创建项目
- 在Idea中新建Maven工程;
- 工程创建完成后添加相应的坐标。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codeaction</groupId>
<artifactId>anno</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
1.2、添加相关类
1.2.1、创建持久层接口
package org.codeaction.dao;
public interface IAccountDao {
void saveAccount();
}
1.2.2、创建持久层接口实现类
package org.codeaction.dao.impl;
import org.codeaction.dao.IAccountDao;
//@Component
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Override
public void saveAccount() {
System.out.println("账户保存成功");
}
}
@Component和@Repository注解下面会讲。
1.2.3、创建业务层接口
package org.codeaction.service;
public interface IAccountService {
void saveAccount();
}
1.2.4、创建业务层接口实现类
package org.codeaction.service.impl;
import org.codeaction.dao.IAccountDao;
import org.codeaction.dao.impl.AccountDaoImpl;
import org.codeaction.service.IAccountService;
//@Component
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
@Component
作用:把资源让Spring来管理,相当于在XML中配置了一个bean;
属性:只有一个value属性,用来指定id。如果不指定value属性,默认bean的id是当前类的类名,首字母小写。
@Controller、@Service、@Repository
作用和属性与@Component完全一样,但是它们提供了更加明确的语义。
@Controller:用于视图层的注解
@Service:用于业务层的注解
@Repository:用于持久层的注解
1.3、添加XML配置文件
XML文件在resource目录下。这个文件也可以不写,但是不写如何配置,后面的教程会讲。
<?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">
<!-- 告知spring创建容器时要扫描的包 -->
<context:component-scan base-package="org.codeaction"></context:component-scan>
</beans>
1.4、添加测试类
创建带有main方法的类,用来进行测试
package org.codeaction.ui;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.codeaction.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountUI {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IAccountService accountService = (IAccountService) context.getBean("accountService");
IAccountDao accountDao = (IAccountDao) context.getBean("accountDao");
System.out.println(accountService);
System.out.println(accountDao);
}
}
运行main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@5f71c76a
org.codeaction.dao.impl.AccountDaoImpl@1d7acb34
通过上面的内容,我们学习了如何通过注解配置bean,在AccountServiceImpl中,accountDao属性没有被注入值,接下来我们学习一下如何注入值,也就是使用注解实现DI。
二、使用注解实现DI
2.1、修改业务层接口实现类
package org.codeaction.service.impl;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
@Autowired
作用:
- 自动按照类型注入;
- 当使用此注解注入属性时,set方法可以省略,它只能注入bean类型;
- 当有多个类型匹配时(2.3会讲这种情况),使用要注入的对象变量名称作为bean的id,在Spring容器中查找,找到了可以注入成功,找不到就报错。
2.2、修改测试类
package org.codeaction.ui;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.codeaction.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountUI {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IAccountService accountService = (IAccountService) context.getBean("accountService");
IAccountDao accountDao = (IAccountDao) context.getBean("accountDao");
System.out.println(accountService);
System.out.println(accountDao);
accountService.saveAccount();
}
}
运行main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@1188e820
org.codeaction.dao.impl.AccountDaoImpl@2f490758
11111111111111111111111111111
2.3、自动类型注入多个类型匹配的情况
2.3.1、新增业务层接口实现类
package org.codeaction.dao.impl;
import org.codeaction.dao.IAccountDao;
import org.springframework.stereotype.Repository;
@Repository("accountDao1")
public class AccountDaoImpl1 implements IAwccountDao {
@Override
public void saveAccount() {
System.out.println("222222222222222222222222");//注意这个打印输出
}
}
运行2.2中的main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@33b37288
org.codeaction.dao.impl.AccountDaoImpl@77a57272
11111111111111111111111111111
大家注意,这里输出了“11111111111111111111111111111”,证明@Autowired自动注入在有多个类型匹配时,使用要注入的对象变量名称作为bean的id,如果存在,依然可以注入成功。如果此时我希望注入AccountDaoImpl1的对象应该如何做呢?
2.3.2、注入特定id的bean对象(方式1)
修改业务层接口实现类,代码如下:
package org.codeaction.service.impl;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
@Qualifier("accountDao1")
private IAccountDao accountDao;
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
运行2.2中的main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@77a57272
org.codeaction.dao.impl.AccountDaoImpl@7181ae3f
222222222222222222222222
这里输出了“222222222222222222222222”,证明我们使用@Autowired结合 @Qualifier实现了特定id的bean对象的注入。
@Qualifier
作用:
- 在自动按照类型注入的基础之上,再按照bean的id注入;
- 给方法注入参数;
- 在给属性注入时,不能独立使用,必须和@Autowired一起使用(我们目前案例讲的就是这种情况),给方法注入参数时,可以独立使用。
属性:只有一个value,指定bean的id。
上面的案例要使用两个注解,能不能一个注解就搞定?
2.3.3、注入特定id的bean对象(方式2)
修改业务层接口实现类,代码如下:
package org.codeaction.service.impl;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
//@Autowired
//@Qualifier("accountDao1")
@Resource(name = "accountDao1")
private IAccountDao accountDao;
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
运行2.2中的main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@77a57272
org.codeaction.dao.impl.AccountDaoImpl@7181ae3f
222222222222222222222222
这里输出了“222222222222222222222222”,证明我们使用@Resource实现了特定id的bean对象的注入。
@Resource
作用:直接按照bean的id注入,只能注入bean类型。
属性:name,指定bean的id。
2.3.4、注入基本数据类型和String类型
package org.codeaction.service.impl;
import org.codeaction.dao.IAccountDao;
import org.codeaction.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Value("hello world")
private String test;
//@Autowired
//@Qualifier("accountDao1")
@Resource(name = "accountDao1")
private IAccountDao accountDao;
@Override
public void saveAccount() {
System.out.println(this.test);
accountDao.saveAccount();
}
}
运行2.2中的main方法,控制台输出如下:
org.codeaction.service.impl.AccountServiceImpl@3e77a1ed
org.codeaction.dao.impl.AccountDaoImpl@3ffcd140
hello world
100
222222222222222222222222
这里输出了“hello world”和“100”,证明我们使用@Value能够注入基本数据类型和String类型。
@Value
作用:注入基本数据类型和 String 类型数据的。
属性:只有一个value,用于指定值 。
三、其他注解
3.1、@Scope
作用:指定bean的作用范围。
属性:value,用来指定范围,可以取的值包括,singleton、prototype、request、session、globalsession。
3.2、@PostConstruct
作用:用于指定初始化方法。
3.3、@PreDestroy
作用:用于指定销毁方法。