注解开发
# 注解开发
先前我们一直使用applicationContext.xml文件配置bean进行开发,但其实Spring还为我们提供了更便捷的注解开发。
# 小试牛刀
ApplicationContext.xml
<?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 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="com.project.dao.impl"/>
</beans>
2
3
4
5
6
7
8
9
UserDaoImpl.java
@Component("UserDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("Save running!");
}
}
2
3
4
5
6
7
8
不难发现,此时ApplicationContext.xml已经不需要<bean>
标签了,我们在实现类的上面添加了一个@Component
注解,该注解填写的是<bean>
标签内的ID属性。那么程序如何得知你哪个类写了Component呢?
ApplicationContext.xml中多了一行<context:component-scan base-package="com.project.dao.impl"/>
,这行的作用是用来扫描指定包中所有类是否包含component,你甚至可以简写为<context:component-scan base-package="com.project"/>
![[Pasted image 20220612150036.png]]
这三个注解功能完全一致,只是为了语义化而已
# 纯注解开发模式
上面的模式,我们applicationContext.xml完全就剩下context了,能否把这也省了?是可以的! 我们可以用类来代替配置文件。
我们可以定义一个类(随意命名),然后为其写上两个注解
@Configuration
@ComponentScan("com.project")
public class SpringConfig {
}
2
3
4
@Configuration代表的是:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
2
3
4
5
6
7
8
9
@ComponentScan代表的是
<context:component-scan base-package="com.project"/>
这样一来,我们就可以彻底告别applicationContext.xml
文件了
但问题来了,我们在主类是通过new ClassPathXmlApplicationContext()
获取配置文件对象的,现在该如何获取类配置对象呢?
其实还有一个叫做AnnotationConfigApplicationContext
的实现类,该类接受的参数就是配置类。假设我们配置类是SpringConfig.class
new AnnotationConfigApplicationContext(SpringConfig.class);
![[Pasted image 20220612161336.png]]
![[Pasted image 20220612161408.png]]
# Bean配置
<bean ... scope="singleton"/>
:
@Scope("singleton")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("Save running!");
}
}
2
3
4
5
6
7
<bean ... init-method="afterPropertiesSet" destroy-method="destroy"/>
:
Java8前:
@Component("UserDao")
public class UserDaoImpl implements UserDao{
@Override
public void save() {
System.out.println("Save running!");
}
@PreDestroy
public void destroy() throws Exception {
System.out.println("destory!");
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
System.out.println("init!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Java8后:
@Component("UserDao")
public class UserDaoImpl implements UserDao, InitializingBean, DisposableBean {
@Override
public void save() {
System.out.println("Save running!");
}
@Override
public void destroy() throws Exception {
System.out.println("destory!");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<bean ... autowire=""/>
:
引用类型
@Component("UserDao")
public class UserDaoImpl implements UserDao{
@Autowired
private TestDao testDao;
@Override
public void save() {
System.out.println("Save running!");
testDao.save();
}
}
2
3
4
5
6
7
8
9
10
这是一个极其明显的重大改善!在需要自动装填的变量上添加注解就行了,从此连setter都不需要了
简单类型
@Component("UserDao")
public class UserDaoImpl implements UserDao{
@Value("12")
private int num;
@Override
public void save() {
System.out.println("Save running!"+num);
}
}
2
3
4
5
6
7
8
9
但问题来了,我写个@Value为啥不干脆直接赋值??
# Properties加载
注释开发加载Properties共有三步:
- 有properties文件
- 配置类声明properties
- 使用properties数据
//jdbc.properties
name=Tommy
2
// 配置类
@Configuration
@ComponentScan("com.project")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
2
3
4
5
6
7
// UserDaoImpl.java
@Component("UserDao")
public class UserDaoImpl implements UserDao{
@Value("${jdbc.password}")
private String num;
@Override
public void save() {
System.out.println("Save running!"+num);
}
}
2
3
4
5
6
7
8
9
10
这样就解决上面提到的问题了
第三方管理
先前我们可以通过<bean class="xx.xx.xx.Hello"/>
的方式管理第三方Bean,但你使用注释方式,总不可能去别人的包里直接改代码吧?
Spring编写者为后来开发人员提供了手动加载Bean对象的方法
在配置类中声明一个方法返回第三方的类,并在该方法内初始化信息。
@Configuration
@ComponentScan("com.project")
@PropertySource("jdbc.properties")
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///testing");
ds.setUser("root");
ds.setPassword("root");
return ds;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
然后就可以去主类中去使用了
DataSouce dataSource = ac.getBean(DataSource.class);
但往后一大堆第三方类岂不都得写在这里?很难管理啊! 因此,你可以创建其他类,例如jdbcConfig.java
public class jdbcConfig(){
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///testing");
ds.setUser("root");
ds.setPassword("root");
return ds;
}
}
2
3
4
5
6
7
8
9
10
11
然后在主配置类中添加注释@Import(jdbcConfig.class)
即可完成导入!
第三方简单类型注入 ![[Pasted image 20220612180023.png]] 第三方引用类型注入 ![[Pasted image 20220612180045.png]]
# Component和Bean
@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。 @Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑
← 容器 xml配置与注解对比→