Spring注解驱动开发[自用]--02

Spring注解驱动开发

7. 生命周期-@Bean指定初始化和销毁方法

bean的生命周期:
bean创建—初始化—销毁的过程
容器管理bean的生命周期:
我们可以自定义初始化和销毁方法;容器在bean进行当前生命周期的时候来调用我们自定义的初始化和销毁方法
构造(对象创建)
单实例,在容器启动的时候创建对象
多实例,在每次获取的时候创建对象
初始化:
对象创建完成,并赋值好,调用初始化方法。。。
销毁:
单实例:容器关闭的时候
多实例:容器不会管理这个baen,容器不会调用销毁方法。
1)、指定初始化和销毁方法:
指定init-method和destroy-method

首先第一步创建bean对象 Car.java

public class Car {

    public Car(){
        System.out.println("car constructor...");
    }

    public void init(){
        System.out.println("car ... init...");
    }

    public void destroy(){
        System.out.println("car ... destroy...");
    }
}

第二步、创建我的生命周期配置类

@Configuration
public class MyConfigOfLifeCycle {

    @Scope("prototype") //多实例不到用销毁方法
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

第三步、测试容器生命周期

public class IOCTest_LifeCycle {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfLifeCycle.class);

        //获取bean,如果不获取bean,多实例只有容器
        applicationContext.getBean(Car.class);
        System.out.println("容器创建完成...");

        applicationContext.close();
    }
}

第四步、运行结果

image-20230314163112063

8. 生命周期-InitializingBean和DisposableBean

1)、指定初始化和销毁方法:
指定init-method和destroy-method

2)、通过让InitializingBean(定义初始化逻辑),
DisposableBean(定义销毁)

第一步、创建bean—>cat.java

@Component  //将cat放入到容器中
public class Cat implements InitializingBean, DisposableBean {

    public Cat(){
        System.out.println("cat  constructor");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("cat...destroy... ");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat...afterPropertiesSet...");
    }
}

第二步、扫描容器中的cat

@ComponentScan("com.xjz.pojo")///扫描pojo中在容器中的bean
@Configuration//配置类
public class MyConfigOfLifeCycle {

    //@Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

第三步、测试

public class IOCTest_LifeCycle {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfLifeCycle.class);

        //因为单实例,所以注释掉获取bean
        //applicationContext.getBean(Car.class);
        System.out.println("容器创建完成...");

        applicationContext.close();
    }
}

第四步、运行结果

image-20230314163953138

9. 声明周期-@PostConstruct和@PreDestroy

3)、可以使用JSR250;
@PostConstruct:在bean创建完成并且属性赋值完成后,来执行初始化方法
**@PreDestroy:**在容器销毁bean之前通知我们进行清理工作

第一步、创建bean–》Dog.java

@Component  //将Dog可以被容器扫描到
public class Dog {

    public Dog(){
        System.out.println("Dog...constructor...");
    }

    //对象创建并且赋值之后 调用
    @PostConstruct
    public void init(){
        System.out.println("Dog....PostConstruct...");
    }

    //容器移除对象之前  调用
    @PreDestroy
    public void destroy(){
        System.out.println("Dog....PreDestroy...");
    }
}

第二步、扫描容器中的Dog的bean

//3)、可以使用JSR250;
//     @PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法
//     @PreDestroy:在容器销毁bean之前通知我们进行清理工作

@ComponentScan("com.xjz.pojo")
@Configuration //配置类
public class MyConfigOfLifeCycle {

    //@Scope("prototype")//默认为单例
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

第三步、测试

public class IOCTest_LifeCycle {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfLifeCycle.class);

        //applicationContext.getBean(Car.class);
        System.out.println("容器创建完成...");

        applicationContext.close();
    }
}

第四步、运行结果

image-20230314165229299

10. 生命周期-BeanPostProcessor-后置处理器

4)、BeanPostProcessorinterface】,bean的后置处理器
在bean初始化前后进行一些处理工作;
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作

第一步、将后置处理器放入IOC容器中

/**
 * 后置处理器:初始化前后进行处理工作
 * 将后置处理器加入到IOC容器中
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }
}

第二步、测试

@ComponentScan("com.xjz.bean")
@Configuration
public class MyConfigOfLifeCycle {

    //@Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}

第三步、运行结果

image-20230314205145228

初始化前后我们就用BeanPostProcessor即可

BeanPostProcessor.postProcessBeforeInitialization
初始化:
     对象创建完成,并赋值好,调用初始化方法。。。
BeanPostProcessor.postProcessAfterInitialization
销毁:

11. 生命周期-BeanPostProcessor原理

通过7-11四种方式,我们就可以对bean的整个生命周期进行控制:

  • bean的实例化:调用bean的构造方法,我们可以在bean的无参构造方法中执行相应的逻辑。

  • bean的初始化:在初始化时,可以通过BeanPostProcessorpostProcessBeforeInitialization()方法和postProcessAfterInitialization()方法进行拦截,执行自定义的逻辑;通过@PostConstruct注解、InitializingBean和init-method来指定bean初始化前后执行的方法,在该方法中咱们可以执行自定义的逻辑。

  • bean的销毁:可以通过@PreDestroy注解、DisposableBean和destroy-method来指定bean在销毁前执行的方法,在该方法中咱们可以执行自定义的逻辑。

  • 所以,通过上述四种方式,我们可以控制Spring中bean的整个生命周期。

    bean生命周期执行顺序如下:

    构造方法–>属性注入–>后置处理器–>初始化–>后置处理器–>销毁方法

BeanPostProcessor源码解析

populateBean(beanName, mbd, instanceWrapper); // 给bean进行属性赋值
initializeBean(beanName, exposedObject, mbd)
{
	applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	invokeInitMethods(beanName, wrappedBean, mbd); // 执行自定义初始化
	applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

也就是说,在Spring中,调用initializeBean()方法之前,调用了populateBean()方法为bean的属性赋值,为bean的属性赋好值之后,再调用initializeBean()方法进行初始化。

在initializeBean()中,调用自定义的初始化方法(即invokeInitMethods())之前,调用了applyBeanPostProcessorsBeforeInitialization()方法,而在调用自定义的初始化方法之后,又调用了applyBeanPostProcessorsAfterInitialization()方法。至此,整个bean的初始化过程就这样结束了。

  • Spring底层对 BeanPostProcessor 的使用:

bean赋值:注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor

12. 属性赋值-@Value赋值

使用@Value赋值:
1、基本数值
2、可以写SpEL:#{}
3、可以写${};取出配置文件中的值(在运行环境变量里面的值)

第一步、创建Person类,并赋值

public class Person {
    
    @Value("老徐")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    
    //省略无参、有参构造、getter、setter、toString方法...
}

第二步、创建配置类,把Person的bean注入到容器中

@Configuration
public class MyConfigOfPropertyValues {

    @Bean
    public Person person(){
        return new Person();
    }
}

第三步、测试

public class IOCTest_PropertyValue {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfPropertyValues.class);
    @Test
    public void test01(){
        printBeans(applicationContext);
        System.out.println("===========");

        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);//查看person的值
        applicationContext.close();
    }
	//遍历查看容器内所有的bean
    private void printBeans(AnnotationConfigApplicationContext applicationContext){
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String definitionName : definitionNames) {
            System.out.println(definitionName);
        }
    }
}

第四步、运行结果

image-20230314220557959

13. 属性赋值-@PropertySource加载外部配置文件

使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值

第一步、创建properties文件,并赋值k/v

person.nickName=小张三

第二步、加注解

public class Person {
    
    @Value("老徐")
    private String name;
    @Value("#{20-2}")
    private Integer age;
	//取出配置文件中的值(在运行环境变量中的值)
    @Value("${person.nickName}")
    private String nickName;
}

第三步、测试

public class IOCTest_PropertyValue {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfPropertyValues.class);
    @Test
    public void test01(){
        printBeans(applicationContext);
        System.out.println("===========");

        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);

        //配置文件中的值默认加入到环境变量中
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("person.nickName");//查看值
        System.out.println(property);
        applicationContext.close();
    }

第四步、运行结果

image-20230314222809717

14. 自动装配-@Autowired&@Qualifier&@Primary

  1. @Autowired:根据属性类型进行自动装配

  2. @Qualifier:根据名称进行注入这个@Qualifier 注解的使用,和上面@Autowired 一起使用 spring5的笔记

@Autowired:自动注入;
1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean(“bookDao”)
3)、@Qualifier(“bookDao”),使用@Qualifier指定需要装配的组件id,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;
5)、@Primary,让Spring进行自动装配的时候,默认使用首选的bean

​ 也可以继续使用@Qualifter指定需要装配的bean的名字

​ bookService{
@Autowired
​ BookDao bookDao;
​ }

第一步、Dao层

//名字默认是类名首字母小写
@Repository
public class BookDao {

    private String lable = "1";

    public String getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }

    @Override
    public String toString() {
        return "BookDao{" +
                "lable='" + lable + '\'' +
                '}';
    }
}

第二步、Service层

@Service
public class BookService {

    @Qualifier("bookDao")
    @Autowired(required = false)
    private BookDao bookDao;

    public void print(){
        System.out.println(bookDao);
    }

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

第三步、Controller层

@Controller
public class BookController {

    @Autowired
    private BookService bookService;

}

第四步、配置类

@Configuration
@ComponentScan({"com.xjz.service","com.xjz.dao","com.xjz.controller"})
public class MyConfigOfAutowired {

    @Primary
    @Bean("bookDao2")
    public BookDao bookDao(){
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }

}

第五步、测试

public class IOCTest_Autowired {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfAutowired.class);

        BookService bookService = applicationContext.getBean(BookService.class);
        System.out.println(bookService);

//        BookDao bookDao = applicationContext.getBean("bookDao");
//        System.out.println(bookDao);

        applicationContext.close();
    }
}

第六步、运行结果

image-20230314232042601

15. 自动装配-@Resource&@Inject

2)、Spring还支持使用@Resource(JSR250)和Inject(JSR330)[Java规范的注解]
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持@Autowired(required=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样,没有required=false的功能;
**@Autowired:**Spring定义的; @Resource、@Inject都是java规范

  • ① @Resource注解

第一步、Service层添加**@Resource注解**

@Service
public class BookService {

    //@Qualifier("bookDao2")
    //@Autowired(required = false)
    @Resource(name = "bookDao2")
    //@Inject
    private BookDao bookDao;

    public void print(){
        System.out.println(bookDao);
    }

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

第二步、测试

public class IOCTest_Autowired {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfAutowired.class);

        BookService bookService = applicationContext.getBean(BookService.class);
        System.out.println(bookService);

//        BookDao bookDao = applicationContext.getBean("bookDao");
//        System.out.println(bookDao);

        applicationContext.close();
    }
}

第三步、运行结果

image-20230314233519621

  • @Inject注解

第一步、导入Javax.inject依赖

 <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

第二步、Service层添加**@Inject注解**

@Service
public class BookService {

    //@Qualifier("bookDao2")
    //@Autowired(required = false)
    //@Resource(name = "bookDao2")
    @Inject
    private BookDao bookDao;

    public void print(){
        System.out.println(bookDao);
    }

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

第三步、测试

public class IOCTest_Autowired {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigOfAutowired.class);

        BookService bookService = applicationContext.getBean(BookService.class);
        System.out.println(bookService);

//        BookDao bookDao = applicationContext.getBean("bookDao");
//        System.out.println(bookDao);

        applicationContext.close();
    }
}

第四步、运行结果

image-20230314233805350

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xjz_2002

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值