Spring注解式编程

spring注解编程-IOC

配置类&Bean注解

@Configuration
加了这个注解的类就相当于传统的一个applicationContext-xxx.xml ,告诉spring这是一个注解类 

最初的Spring只支持xml方式配置Bean,从Spring 3.0起支持:基于Java类的配置方式,Java开发者可以从标签语法里解放了出来。

配置放在哪里

  • 配置类要与启动类同包或者在其任意子包下,满足spring的扫描条件,配置才能被成功加载。
  • 如果不满足上述同包或子包条件,需要如下办法:
    在resources目录下新建META-INF目录,并在该目录下创建spring.factories文件。spring.factories文件内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ft.xx.config.DruidConfig

第一行是spring自动配置的路径,第二行是我们自己要指定加载配置类的路径。

@Bean
@Bean注解的作用与<bean/>标签相同

在标注了@Configuration的类里面的方法上面打上@bean就相当于在applicationContext-xxx.xml配置的一个
<bean id="userDao" class="cn.itsource.dao.UserDao">
简单粗暴理解:@Configuration标注的类等同于一个xml文件,@Bean标注的方法等同于xml文件里的一个<bean/>标签

Bean的名字默认就是方法名,如果想改方法名使用@Bean(“beanName”)

@Configuration 
public class MainConfig {

    @Bean("userDao") //指定bean的名字
    public UserDao userDao(){ // 方法必须是public。
        return new UserDao();
    }
}

通常来说,我们均会把@Bean标注的方法写在@Configuration标注的类里面来配合使用。
但其实,没有@Configuration注解的类中的@Bean也会被扫描到,只是一般不这么用。
是否通过@Configuration,官方管这两种模式分别叫:Full @Configuration和lite @Bean mode。

Full模式和Lite模式
Full模式和Lite模式均是针对于Spring配置类而言的,和xml配置文件无关。

  • Full模式:
运行时会给该类生成一个CGLIB子类放进容器,有一定的性能、时间开销(这个开销在Spring Boot这种拥有大量配置类的情况下是不容忽视的,这也是Spring 5.2新增了proxyBeanMethods属性的最直接原因)
正因为被代理了,所以@Bean方法 不可以是private、不可以是final
  • Lite模式:
    官方定义为:在没有标注@Configuration的类里面有@Bean方法就称为Lite模式的配置。透过源码再看这个定义是不完全正确的,而应该是有如下case均认为是Lite模式的配置类:
类上标注有@Component注解
类上标注有@ComponentScan注解
类上标注有@Import注解
类上标注有@ImportResource注解
若类上没有任何注解,但类内存在@Bean方法

以上case的前提均是类上没有被标注@Configuration,在Spring 5.2之后新增了一种case也算作Lite模式:

标注有@Configuration(proxyBeanMethods = false),注意:此值默认是true,需要显示改为false才算是Lite模式。
自Spring5.2(对应Spring Boot 2.2.0)开始,内置的几乎所有的@Configuration配置类都被修改为了@Configuration(proxyBeanMethods = false),以此来降低启动时间,为Cloud Native继续做准备。

Lite模式下:

配置类本身不会被CGLIB增强,放进IoC容器内的就是本尊
不能直接声明@Bean之间的依赖:配置类内部不能通过方法调用来处理依赖,每次生成的都是一个新实例而并非IoC容器内的单例。(full 模式时,一个@Bean的方法调用了另一@Bean方法,被调用的bean并不会执行两次噢,会保证单例~~)
配置类就是一普通类,所以@Bean方法可以使用private/final/static等进行修饰
  • @Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy。

注入Bean

AnnotationConfigApplicationContext

基于applicationContext-xxx.xml创建的bean是通过 ClassPathXmlApplicationContext(“xxx.xml”)来获取。

基于注解配置类创建的bean,要通过 new AnnotationConfigApplicationContext(MainConfig.class);来获取。

public class Application {

    public static void main(String[] args) {
    
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        UserDao userDao = context.getBean(UserDao.class);
  
    }
}
  1. 前提:
@Configuration
public class MainConfig {

    @Bean
    public UserDao userDao() {
        return new UserDao();
    }
}

此种方式常用于将第三方jar中的某个类,注册为当前项目的一个bean。

  1. 或者:
@Import(UserDao.class)
@Configuration
public class MainConfig {

}
  1. 或者:
@ComponentScan
@Configuration
public class MainConfig {

    @Bean
    public UserDao userDao() {
        return new UserDao();
    }
}

@Component
public class userDao {
}
@Repository,@Service,@Controller,@Component

使用注解的类会被创建出一个bean

  • @ComponentScan
    使用 @Component等创建的bean,需要配置使用@ComponentScan扫描才能识别到这些bean。
    @ComponentScan 其实就是:
<context:component-scan base-package="cn.itsource"/>.

@ComponentScan 可以指定多个路径,还可以指定路径下只包含部门类、排除部分类

@Lazy

指定bean懒加载,容器创建时不加载,第一次使用时才加载

@Scope

指定bean作用域

@Conditional-按照条件注册

类和方法上都可以
如:@Conditional(value = WindowsCondition.class) 表示根据当前os.name的环境来判断是否创建bean

@Import
@Import(Class<?>[] value)

可用于导入任意指定的如第三方jar中的类并自动创建bean到当前容器,也可以导入配置类,则配置类中所有@Bean的bean都能注册到当前容器。

对于第三方jar中的bean,并不能直接注册到当前容器,想要办到:

  1. 这个bean的包名是当前容器启动类的子包(哪怕在不同模块,只要编译后是子包就行)
  2. 不是子包的话,可以使用包扫描指定额外的包的范围,@ComponentScan(),如果有多个额外的包就要写很多。
  3. 不是子包的话,可以使用@Import指定具体的类,每一个想注册进容器的类都要单独写,也会很多。
  4. 由第三方jar提供一个@Enable开头的注解,这个注解就是对@Import(自己的类Class),的封装,对每一个想注册进当前容器的bean,都需要添加一个对应的@Enable开头的注解。
  5. @EnableAutoConfig
@Import(Class value)

导入自定义的ImportSelector选择器,重写selectImports()方法,方法返回需要被导入的组件的类全限定名数组 -springboot底层用的多

@Import(MyImportSelector.class)
public class MyImportSelector implements ImportSelector {
    
    @Override
    public String[] selectImports(Anno..) {
        
        return new String[]{"com.example.User","com.example.Person"}
    }
}

  • Springboot 就是使用 ImportSelector 的方式,详细过程整理在 Spring Boot一篇中。
@Import(Class value)

通过bean定义注册器手动项目spring中容器中注册。 也需要覆写方法registerBeanDefinitions(),其中第二个参数,可以用于向我们的IOC容器注册bean。

@Import(MyImportBeanDefinitionRegistrar.class)
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    @Override
    public viod registerBeanDefinitions(Anno... anno, BeanDefinitionRegistry registry) {
        
        BeanDefinition beanDefinition =  BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        
        registry.registerBeanDefinition("user", beanDefinition)  // (String beanName, BeanDefinition beanDefinition)
    }
}

生命周期管理

  1. 方式一 : @Bean(initMethod = “init”,destroyMethod = “destory”)
  2. 方式二 : 实现InitializingBean和DisposableBean接口
    InitializingBean:afterPropertiesSet(), 设置完属性后调用
    DisposableBean:destroy(), 容器关闭时调用


  1. 方式三 : 注解@PostConstruct @PreDestroy
@Component
public class Test {

    public Test(){
        System.out.println("Test ....create....");
    }

    @PostConstruct
    public void init(){
        System.out.println("Test ....init....");
    }

    @PreDestroy
    public void destory(){
        System.out.println("Test ....destory....");
    }
}
  1. 方式四 : BeanPostProcessor(接口),bean后置处理器
  • Object postProcessBeforeInitialization:初始化之前调用
  • Object postProcessAfterInitialization:初始化之后调用
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    //初始化之前调用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization "+beanName);
        return bean;
    }

    //初始化之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization "+beanName);
        return bean;
    }
}

BeanFactory 和 FactoryBean

区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似

最常用MVC注解

@PathVariable 放置在参数前,用来接受路径参数。

@RequestBody 允许request的参数在request体中,而不是在直接链接在地址的后面。此注解放置在参数前。

@ResponseBody 将返回值放在response体内。返回的是数据而不是页面

@RestController 组合注解,组合了@Controller和@ResponseBody,当我们只开发一个和页面交互数据的控制层的时候可以使用此注解。

@RequestMapping 用来映射web请求(访问路径和参数)。可以注解在类和方法上,注解在方法上的路径会继承注解在类上的路径。
同时支持Serlvet的request和response作为参数,也支持对request和response的媒体类型进行配置。其中有value(路径),produces(定义返回的媒体类型和字符集),method(指定请求方式)等属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值