Spring注解开发
注解开发定义Bean对象
目的:xml配置Bean对象有些繁琐,使用注解简化Bean对象的定义。
基本使用
- 在applicationContext.xml中开启Spring注解包扫描:
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="edu.heuet"/> </beans>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component("bookDao") public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } } @Component public class BookServiceImpl implements BookService { private BookDao bookDao;
public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; }
public void save() { System.out.println("book service save ..."); bookDao.save(); } }
|
补充说明:如果@Component注解没有使用参数指定Bean的名称,那么类名首字母小写就是Bean在IOC容器中的默认名称。例如:BookServiceImpl对象在IOC容器中的名称是bookServiceImpl。
1 2 3 4 5 6 7 8 9 10
| public class AppForAnnotation { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); System.out.println(bookDao); BookService bookService = ctx.getBean(BookService.class); System.out.println(bookService); } }
|
注意:在测试类中不要调用bookService的save方法,因为还没有给BookServiceImpl中的bookDao赋值,调用bookService的save方法会出现空指针异常。
@Component三个衍生注解
说明:加粗的注解为常用注解。
- Spring提供**
@Component
**注解的三个衍生注解。- **
@Controller
**:用于表现层bean定义。 - **
@Service
**:用于业务层bean定义。 @Repository
:用于数据层bean定义。
1 2 3 4 5 6 7
| @Repository("bookDao") public class BookDaoImpl implements BookDao { }
@Service public class BookServiceImpl implements BookService { }
|
纯注解开发模式
纯注解开发模式介绍
1
| @ComponentScan({edu.heuet.service","edu.heuet.dao"})
|
- 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象。
1 2 3 4
| ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
|
代码演示
定义配置类代替配置文件
1 2 3 4 5 6 7 8
| @Configuration
@ComponentScan("edu.heuet")
public class SpringConfig { }
|
在测试类中加载配置类,获取Bean对象并使用
1 2 3 4 5 6 7 8 9 10 11
| public class AppForAnnotation { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); BookDao bookDao = (BookDao) ctx.getBean("bookDao"); System.out.println(bookDao); BookService bookService = ctx.getBean(BookService.class); System.out.println(bookService); } }
|
注解开发Bean作用范围和生命周期管理
bean作用范围注解配置
1 2 3 4
| @Repository @Scope("singleton") public class BookDaoImpl implements BookDao { }
|
bean生命周期注解配置
- 使用@PostConstruct、@PreDestroy定义bean生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Repository @Scope("singleton") public class BookDaoImpl implements BookDao { public BookDaoImpl() { System.out.println("book dao constructor ..."); } @PostConstruct public void init(){ System.out.println("book init ..."); } @PreDestroy public void destroy(){ System.out.println("book destory ..."); } }
|
注意:@PostConstruct和@PreDestroy注解是jdk中提供的注解,从jdk9开始,jdk中的javax.annotation包被移除了,也就是说这两个注解就用不了了,可以额外导入一下依赖解决这个问题。
1 2 3 4 5
| <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
|
注解开发依赖注入
使用@Autowired注解开启自动装配模式(按类型)
1 2 3 4 5 6 7 8 9 10 11
| @Service public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao;
public void save() { System.out.println("book service save ..."); bookDao.save(); } }
|
说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默认按照类型自动装配,如果IOC容器中同类的Bean有多个,那么默认按照变量名和Bean的名称匹配,建议使用@Qualifier注解指定要装配的bean名称。
注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法。
使用@Qualifier注解指定要装配的bean名称
目的:解决IOC容器中同类型Bean有多个装配哪一个的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public class BookServiceImpl implements BookService { @Autowired @Qualifier("bookDao") private BookDao bookDao;
public void save() { System.out.println("book service save ..."); bookDao.save(); } }
|
注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用。
使用@Value实现简单类型注入
1 2 3 4 5 6 7 8 9 10
| @Repository("bookDao") public class BookDaoImpl implements BookDao { @Value("${name}") private String name;
public void save() { System.out.println("book dao save ..." + name); } }
|
- 以上@Value注解中使用
${name}
从属性文件中读取name
值,那么就需要在配置类或者配置文件中加载属性文件。
1 2 3 4 5 6
| @Configuration @ComponentScan("edu.heuet")
@PropertySource({"classpath:jdbc.properties"}) public class SpringConfig { }
|
注意:@PropertySource()中加载多文件请使用数组格式配置,不允许使用通配符*。
注解开发管理第三方Bean
单独定义配置类
1 2 3 4 5 6 7 8 9 10 11 12
| public class JdbcConfig { @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName("com.mysql.cj.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/spring_db"); ds.setUsername("root"); ds.setPassword("123456"); return ds; } }
|
将独立的配置类加入核心配置
@Import注解导入式
1 2 3 4 5 6
| @Configuration @ComponentScan("edu.heuet")
@Import({JdbcConfig.class}) public class SpringConfig { }
|
@ComponentScan扫描式
1 2 3 4 5
| @Configuration
@ComponentScan({"edu.heuet.config","edu.heuet.service","edu.heuet.dao"}) public class SpringConfig { }
|
注解开发为第三方Bean注入资源
简单类型依赖注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class JdbcConfig { @Value("com.mysql.cj.jdbc.Driver") private String driver; @Value("jdbc:mysql://localhost:3306/spring_db") private String url; @Value("root") private String userName; @Value("123456") private String password; @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }
|
说明:如果@Value()中使用了EL表达式读取properties属性文件中的内容,那么就需要加载properties属性文件。
引用类型依赖注入
1 2 3 4 5 6 7 8 9 10 11
| @Bean public DataSource dataSource(BookDao bookDao){ System.out.println(bookDao); DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; }
|
说明:引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。
总结