注解开发

在使用@Component注解时出现ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn’t supported yet错误。

原因:Spring Framework 5.3.x 版本只能支持 JDK 8-17 (expected),而我原来是JDK 18。

解决:在Project Structure中将project和modules中sources和dependencies的SDK和language level修改为1.8。

之后又出现了java: 错误: 无效的源发行版:18,还需要修改编译器版本。

在setting-build,execution,deployment-compiler-java compiler中将project bytecode version和target byte从的version改为1.8。

定义Bean

注解开发中定义Bean需要先在xml文件中定义注解扫描的包位置,其中base-package可以递归扫描其子路径中所有的包。

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
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="dao"/>

</beans>

然后在要定义的类上添加@Component注解即可。注释掉的另外三种意义等同于Component,可以用来区分MVC结构中的三个层次。

1
2
3
4
5
6
7
8
9
10
@Component("bookDao")
//@Service
//@Repository
//@Controller
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("save...");
}
}

注解中可以不加Bean名,那么在获取Bean时需要填入类。

1
BookDao bookDao = (BookDao) ctx.getBean(BookDao.class);

纯注解开发模式

为了简化开发,可以不使用xml配置文件,直接纯注解开发。

首先需要配置一个Config类,对其加入注解@Configuration表示其是配置类,加入@ComponentScan来扫描路径,使用方式和xml中是一样的。

1
2
3
4
@Configuration
@ComponentScan("dao")
public class SpringConfig {
}

获取容器的方法从配置文件改为从类中获取。

1
2
3
4
5
6
7
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}

作用范围和生命周期

一样只需要添加注解即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Repository
@Scope("prototype")
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("save...");
}
@PostConstruct
public void init() {
System.out.println("init...");
}
@PreDestroy
public void destroy() {
System.out.println("destroy...");
}
}

依赖注入

加入@Autowired即可自动注入,不需要set方法。(使用暴力反射,无参构造方法,需要提供。)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class BookServiceImpl implements BookService {
@Autowired
/*如果有多个相同类型的Bean,可以这样指定名称。
@Qualifier("bookDao")*/
private BookDao bookDao;

@Override
public void save() {
System.out.println("service save...");
bookDao.save();
}
}

在config中加入@PropertySource注解(不允许使用通配符),也可以从外部properties文件中注入常量,使用@Value注解。

1
2
3
4
5
@Configuration
@ComponentScan({"dao", "service"})
@PropertySource("jdbc.properties")
public class SpringConfig {
}
1
2
3
4
5
6
7
8
9
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("${name}")
private String name;
@Override
public void save() {
System.out.println("dao save..." + name);
}
}

第三方Bean

通过配置文件注入第三方Bean

一般来说Spring的每个配置文件都需要单独配置,然后通过@Import导入一个配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class jdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///db1?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
1
2
3
4
@Configuration
@Import(jdbcConfig.class)
public class SpringConfig {
}

如果需要引用类型的依赖注入,则在Bean中添加形参即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@ComponentScan("dao")
public class jdbcConfig {
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///db1?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}