明确
- 学习基于注解的 IoC 配置,大家脑海里首先得有一个认知,即注解配置和 xml 配置要实现的功能都是一样 的,都是要降低程序间的耦合,只是配置的形式不一样
- 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯。所以这两种配置方式我们都需要掌握(我觉得想xml+注解是比较好的)
- 注解的优势:
配置简单,维护方便(我们找到类,就相当于找到了对应的配置) - XML的优势:
修改时,不用改源码,不涉及重新编译和部署
常用注解
用于创建对象:相当于:< bean id="" class="" > 标签
- @Controller 、@Service 、@Repository 、都是@Component的衍生注解,它们的作用及属性都是一模一样的
注解 | 作用 | 属性 |
---|
@Component | 相当于在 xml 中配置一个 bean | value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名,首字母小写 |
@Controller | 一般用于表现层的注解 | 和@Component一样 |
@Service | 一般用于业务层的注解 | 和@Component一样 |
@Repositor | 一般用于持久层的注解 | 和@Component一样 |
用于注入数据:相当于:< property name="" ref="" > 或< property name="" value="" >标签
注解 | 作用 | 属性 |
---|
@Autowired | 自动按照类型注入,当使用注解注入属性时,set方法可以省略。它只能注入其他 bean 类型。当有多个 类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 Spring 容器查找,找到了也可以注入成功。找不到就报错 | required:默认为true,该bean必须存在,否则就会注入失败 |
@Qualifier | 在自动按照类型注入的基础之上,再按照 Bean 的 id 注入,它在给字段注入时不能独立使用,必须和 @Autowire 一起使用;但是给方法参数注入时,可以独立使用 | value:指定 bean 的 id |
@Resource | 直接按照 Bean 的 id 注入,它也只能注入其他 bean 类型 | name:指定 bean 的 id |
@Value | 注入基本数据类型和 String 类型数据的 | value:用于指定值 |
用于改变作用范围:相当于:< bean id="" class="" scope="" >
注解 | 作用 | 属性 |
---|
@Scope | 指定 bean 的作用范围 | value:指定范围的值,取值:singleton、prototype、request session、globalsession |
和生命周期相关:(了解)相当于:< bean id="" class="" init-method="" destroy-method="" / >
注解 | 作用 |
---|
@PostConstruct | 用于指定初始化方法 |
@PreDestroy | 用于指定销毁方法 |
和纯注解开发相关
注解 | 作用 | 属性 |
---|
@Configuration | 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用 AnnotationApplicationContext(有@Configuration 注解的类.class) | value:用于指定配置类的字节码 |
@ComponentScan | 用于指定 spring 在初始化容器时要扫描的包,作用和在 spring 的 xml 配置文件中的: < context:component-scan base-package=“com.zsc” />是一样的 | basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样 |
@Bean | 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器 | 和name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id) |
@PropertySource | 用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置 | value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath: |
@Value | 用于获取.properties文件中的值,与@PropertySource对应 | value:用于指定.properties文件里面的key值 |
@Import | 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题 | value[]:用于指定其他配置类的字节码 |
通过注解获取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
基于纯注解的CRUD操作案例
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
@Data
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
}
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner runner;
public void save(Account account) {
try {
runner.update("insert into account(name,money)values(?,?)", account.getName(), account.getMoney());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void update(Account account) {
try {
runner.update("update account set name=?,money=? where id=?", account.getName(), account.getMoney(), account.getId());
}catch (Exception e){
throw new RuntimeException(e);
}
}
public void delete(Integer accountId) {
try {
runner.update("delete from account where id=?",accountId);
}catch (Exception e){
throw new RuntimeException(e);
}
}
public Account findById(Integer accountId) {
try {
return runner.query("select * from account where id=?",new BeanHandler<Account>(Account.class),accountId);
}catch (Exception e){
throw new RuntimeException(e);
}
}
public List<Account> findAll() {
try {
return runner.query("select * from account ",new BeanListHandler<Account>(Account.class));
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
public void save(Account account) {
accountDao.save(account);
}
public void update(Account account) {
accountDao.update(account);
}
public void delete(Integer accountId) {
accountDao.delete(accountId);
}
public Account findById(Integer accountId) {
return accountDao.findById(accountId);
}
public List<Account> findAll() {
return accountDao.findAll();
}
}
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springlearn?serverTimezone=UTC
jdbc.username=root
jdbc.password=123
public class JdbcConfiguration {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource")
public DataSource createDataSource(){
try{
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser(username);
ds.setPassword(password);
ds.setJdbcUrl(url);
ds.setDriverClass(driver);
return ds;
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Bean(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
}
@ComponentScan("com.zsc")
@Import(JdbcConfiguration.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class test {
@Autowired
private IAccountService accountService;
@Test
public void test(){
System.out.println("测试查询全部操作");
List<Account> lists = accountService.findAll();
lists.forEach(System.out::println);
System.out.println("测试按id查找操作");
Account account = accountService.findById(1);
System.out.println(account);
System.out.println("测试保存操作");
Account account1 = new Account();
account1.setMoney(2000f);
account1.setName("test");
accountService.save(account1);
System.out.println("测试删除操作");
accountService.delete(1);
}
}