Bootstrap

7.spring框架-----注解开发

目录

一、注解开发定义bean

1.@Component注解

二、纯注解开发,不需要配置文件

1.@Configuration

2.@ComponentScan

三、注解开发bean作用范围与生命周期管理

1.Bean的作用范围

1.1@scope注解

2.Bean的生命周期

2.1@PostConstruct注解

2.2@PreDestroy注解

四、注解开发依赖注入

1.注解实现按照类型注入

1.1@Autowired注解

2.注解实现按照名称注入

2.1@Qualifier注解

3.简单数据类型注入

3.1@Value注解

4.注解读取properties配置文件

4.1@PropertySource注解

五、IOC/DI注解开发管理第三方bean

1.注解开发管理第三方bean

1.1@Bean注解

六.引入外部配置类

1.使用包扫描引入

2.使用@Import引入

2.1@Import注解

七、注解开发实现为第三方bean注入资源

1.简单数据类型

2.引用数据类型

八、注解开发总结


一、注解开发定义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;
    }
}

八、注解开发总结

 

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;