目录
一、注解开发定义bean
使用注解的形式替代 xml 配置,将繁杂的 Spring 配置文件从工程中彻底消除掉,简化书写。
添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
public void save() {
System.out.println("book service save ...");
}
}
1.@Component注解
在BookDaoImpl类和BookDaoServiceImpl类上添加@Component注解
@Component注解不可以添加在接口上,因为接口是无法创建对象的
@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 save() {
System.out.println("book service save ...");
bookDao.save();
}
public void setBookDao(BookDaoImpl bookDao) {
this.bookDao = bookDao;
}
}
配置Spring的注解包扫描,在配置文件中添加
<context:component-scan base-package="com.itheima"/>
运行文件
public class AppForLifeCycle {
public static void main( String[] args ) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
//按类型获取bean
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
二、纯注解开发,不需要配置文件
使用Java类替代配置文件
1.@Configuration
注解用于设定当前类为配置类
2.@ComponentScan
注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
public void save() {
System.out.println("book service save ...");
}
}
创建一个配置类SpringConfig,在配置类上添加@Configuration注解,将其标识为一个配置类,替换applicationContext.xml,在配置类上添加包扫描注解@ComponentScan替换
@Configuration
@ComponentScan({"com.demo.dao","com.demo.service"})
public class SpringConfig {
}
运行文件
public class AppForLifeCycle {
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作用范围与生命周期管理
添加一个配置类SpringConfig,添加BookDao、BookDaoImpl类,和运行类
@Configuration
@ComponentScan("com.demo.dao")
public class SpringConfig {
}
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
public class AppForLifeCycle {
public static void main( String[] args ) {
ApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
}
}
1.Bean的作用范围
在控制台打印两个一摸一样的地址,说明默认情况下bean是单例
要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解
1.1@scope注解
@Repository
@Scope("prototype")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
2.Bean的生命周期
2.1@PostConstruct注解
在构造方法之后执行,替换 init-method
2.2@PreDestroy注解
在销毁方法之前执行,替换 destroy-method
在BookDaoImpl中添加两个方法,init和destroy,在对应的方法上添加@PostConstruct和@PreDestroy注解即可。
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
@PostConstruct
public void init() {
System.out.println("init ...");
}
@PreDestroy
public void destroy() {
System.out.println("destroy ...");
}
}
运行方法
public class AppForLifeCycle {
public static void main( String[] args ) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
ctx.close();
}
}
四、注解开发依赖注入
添加一个配置类SpringConfig,添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
@Configuration
@ComponentScan("com.demo")
public class SpringConfig {
}
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
@Service
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void setBookDao(BookDaoImpl bookDao) {
this.bookDao = bookDao;
}
}
1.注解实现按照类型注入
在BookServiceImpl类的bookDao属性上添加@Autowired注解
1.1@Autowired注解
@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,比如添加 BookDaoImpl2 ,此时,按照类型注入就无法区分到底注入哪个对象,此时需要按照名称注入
@Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和 Bean的名称匹配。因为变量名叫bookDao而容器中也有一个booDao,所以可以成功注入。
2.注解实现按照名称注入
当根据类型在容器中找到多个bean,注入参数的属性名又和容器中bean的名称不一致,就需要使用到@Qualifier来指定注入哪个名称的bean对象。
2.1@Qualifier注解
@Qualifier不能独立使用,必须和@Autowired一起使用
@Configuration
@ComponentScan("com.demo")
public class SpringConfig {
}
public interface BookDao {
public void save();
}
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
public interface BookService {
public void save();
}
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao")
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
运行文件
public class AppForLifeCycle {
public static void main( String[] args ) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
BookService bookService = ctx.getBean(BookService.class);
bookService.save();
}
}
3.简单数据类型注入
数据类型换了,对应的注解也要跟着换,这次使用@Value注解,将值写入注解的参数中就行了
3.1@Value注解
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("name")
private String name;
public void save() {
System.out.println("book dao save ..."+name);
}
}
4.注解读取properties配置文件
有时候使用@Value需要从外部传入参数,一般会被用在从properties配置文件中读取内容进行使用
jdbc.properties
name=name12345
在配置类上添加@PropertySource注解
4.1@PropertySource注解
@Configuration
@ComponentScan("com.demo")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
使用@Value读取配置文件中的内容
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("${name}")
private String name;
public void save() {
System.out.println("book dao save ..."+name);
}
}
如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个
@PropertySource({"jdbc.properties","jdbc2.properties"})
@PropertySource注解属性中不支持使用通配符* ,运行会报错
@PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件
@PropertySource({"classpath:jdbc.properties"})
五、IOC/DI注解开发管理第三方bean
添加BookDao类和BookDaoImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
在配置类中添加一个方法 该方法的返回值就是要创建的Bean对象类型,在方法上添加@Bean注解
1.注解开发管理第三方bean
1.1@Bean注解
将方法的返回值制作为Spring管理的一个bean对象
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/bookshop");
ds.setUsername("root");
ds.setPassword("12345");
return ds;
}
}
不能使用DataSource ds = new DruidDataSource() 因为DataSource接口中没有对应的setter方法来设置属性。
运行文件
public class AppForLifeCycle {
public static void main( String[] args ) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
六.引入外部配置类
如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅 读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?
1.使用包扫描引入
在Spring的配置类上添加包扫描
@Configuration
@ComponentScan("com.demo.config")
public class SpringConfig {
}
在JdbcConfig上添加配置注解
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/bookshop");
ds.setUsername("root");
ds.setPassword("12345");
return ds;
}
}
运行文件
public class AppForLifeCycle {
public static void main( String[] args ) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
依然能获取到bean对象并打印控制台。 这种方式虽然能够扫描到,但是不能很快的知晓都引入了哪些配置类,所有这种方式不推荐使用。
2.使用@Import引入
2.1@Import注解
@Import参数需要的是一个数组,可以引入多个配置类。
@Import注解在配置类中只能写一次
配置文件
@Configuration
@Import({JdbcConfig.class})
public class SpringConfig {
}
重新运行程序
七、注解开发实现为第三方bean注入资源
在使用@Bean创建bean对象的时候,有时候需要简单数据类型和引用数据类型
1.简单数据类型
使用@Value注解引入值
@Configuration
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/bookshop")
private String url;
@Value("root")
private String userName;
@Value("12345")
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;
}
}
2.引用数据类型
假设在构建DataSource对象的时候,需要用到BookDao对象,那就需要把BookDao对象注入进方法内
在SpringConfig中扫描BookDao 扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象
@Configuration
@ComponentScan("com.demo.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}
@Configuration
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/bookshop")
private String url;
@Value("root")
private String userName;
@Value("12345")
private String password;
@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;
}
}
八、注解开发总结