spring 常用注解

    技术2023-12-21  76

    spring 注解开发

    @Configuration

    @Configuration //告诉spring这是一个配置类

    给容器注册组件

    非注解

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.ljq.bean.Person" id="person"> <property name="age" value="18"></property> <property name="name" value="张三"></property> </bean> </beans>

    注解

    /** * 给容器注册组件: *1)、包扫描(@ComponentScan)+组件标注注解(@Controller/@Service/@Repository/@Component) *2)、@bean[导入第三方包里面的组件] *3)、@Import[快速给容器中导入一个主键] * 1、@Import(要导入容器的主键):容器就会自动注册这个组件,id默认是全类名 * 2、ImportSelector:返回需要导入组件的全类名 * 3、ImportBeanDefinitionRegistrar:手动注册bean到容器中 * 4)使用Spring提供的FactoryBean(工厂Bean) * 1、默认获取到的是工厂bean调用getObject创建的对象 * 2、要获取工厂bean本身需要给id前面加一个& * &colorFactoryBean */
    @Bean
    //配置类==配置文件 @Configuration //告诉spring这是一个配置类 public class MainConfig { //给容器重注册一个Bean;类型为返回值的类型,id默认还是方法名作为id @Bean("person") //id默认为方法名,也可在@Bean中设置 public Person person01(){ return new Person("list",20); } } //测试 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); Person bean = applicationContext.getBean(Person.class); System.out.println(bean);
    @controller@service@repository@component
    @controller用来定义控制(dao)层的组件 @service用来定义业务层(service)的组件 @repository用来定义持久层(domain)的组件 @component用来定义不在上述范围内的一般性组件 上面组件的名称默认是类名的首字母小写,如果要重命名,则这样@controller("beanName")
    @ComponentScan
    @ComponentScan(value = "com.ljq") //要扫描的定义以上注解的包 加入bean容器 @ComponentScan(value = "com.ljq" ,includeFilters = { //@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}), // @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class}), @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class}) } ,useDefaultFilters = false) //@ComponentScan value:指定要扫描的包 // excludeFilters=Filter[],指定扫描时要排除的组件 // ANNOTATION:按照注解 // ASSIGNABLE_TYPE:按照给定类型 // ASPECTJ:使用ASPECTJ表达式 // REGEX:使用正则表达式 // CUSTOM:使用自定义规则 /** * @ComponentScan(value = "com.ljq" ,excludeFilters = { * @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})}) 排除Controller标签 * * */ // includeFilters=Filter[],指定扫描时只需要包含那些组件 /** * @ComponentScan(value = "com.ljq" ,includeFilters = { * @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})} ,useDefaultFilters = false) */

    自定义规则

    public class MyTypeFilter implements TypeFilter { /** *MetadataReader:读取到的当前正在扫描的类的信息 *MetadataReaderFactory:可以获取到其他任何类信息 */ public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类资源信息(类路径) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println("-->"+className); if(className.contains("er")){ return true; } return false; } }
    @Scope
    //@Scope 调整作用域,默认是单实例的 /** * prototype:多实例的:ioc容器启动并不会去调用方法放在容器中 * 每次获取的时候才会调用方法创建对象 * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放入ioc容器中 * 以后每次获取直接从容器(map.get)中拿 * request:同一次请求创建一次实例 * session:同一个session创建一个实例 * * */ // @Scope("prototype") //控制作用范围
    @Lazy
    懒加载: 单实例bean:默认在容器启动的时候创建对象 懒加载:容器启动时不创建对象,第一次使用(获取时创建对象)
    @Import

    [快速给容器中导入一个主键]

    1、@Import(要导入容器的主键):容器就会自动注册这个组件,id默认是全类名

    在配置类中

    @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) //导入组件,id默认是全类名

    2、ImportSelector:返回需要导入组件的全类名

    public class MyImportSelector implements ImportSelector { //放回值就是要导入到容器中的主键全类名 //AnnotationMetadata:当前标注@Import注解的类的所有信息 public String[] selectImports(AnnotationMetadata annotationMetadata) { //方法不能返回null值 return new String[]{"com.ljq.bean.Blue","com.ljq.bean.Yellow"}; } } 3、ImportBeanDefinitionRegistrar:手动注册bean到容器中 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param annotationMetadata:当前类的注解信息 * @param beanDefinitionRegistry:BeanDefinition注册类: * 把所有需要添加到容器中的bean:调用 * BeanDefinitionRegistry.registerBeanDefinition手动注册 */ public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { boolean definition = beanDefinitionRegistry.containsBeanDefinition("com.ljq.bean.Red"); boolean definition1 = beanDefinitionRegistry.containsBeanDefinition("com.ljq.bean.Blue"); if (definition&&definition1){ //指定bean定义信息,(bean的类型,bean。。。) RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); //注册一个bean,指定bean名 beanDefinitionRegistry.registerBeanDefinition("rainBow",beanDefinition); } } }
    使用Spring提供的FactoryBean(工厂Bean)
    public class ColorFactoryBean implements FactoryBean<Color> { //返回一个Color对象,这个对象会添加到容器中 public Color getObject() throws Exception { System.out.println("................"); return new Color(); } public Class<?> getObjectType() { return Color.class; } //是单例吗? //true:这个bean是单例在容器中只会保存一份 //false:多实例,每次获取都会创建一个新的 public boolean isSingleton() { return false; } }

    需要在配置类中

    @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); }

    测试

    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();//看到容器中所有的Bean Blue bean = applicationContext.getBean(Blue.class); System.out.println(bean); //工厂Bean获取的是调用getObject创建的对象 Object colorFactoryBean = applicationContext.getBean("colorFactoryBean"); Object colorFactoryBean1 = applicationContext.getBean("colorFactoryBean"); Object colorFactoryBean2 = applicationContext.getBean("&colorFactoryBean"); ColorFactoryBean colorFactoryBean3 = applicationContext.getBean(ColorFactoryBean.class); System.out.println(colorFactoryBean==colorFactoryBean1); System.out.println("bean类型"+colorFactoryBean.getClass()); System.out.println("bean类型2"+colorFactoryBean2.getClass()); System.out.println("bean类型3"+colorFactoryBean2.getClass()); false bean类型class com.ljq.bean.Color bean类型2class com.ljq.bean.ColorFactoryBean bean类型3class com.ljq.bean.ColorFactoryBean

    1、默认获取到的是工厂bean调用getObject创建的对象

    2、要获取工厂bean本身需要给id前面加一个&

    ​ &colorFactoryBean

    bean的生命周期

    bean的生命周期: * bean创建---初始化---销毁的过程 * 容器管理bean的生命周期 * 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命的时候来调用我们自定义的初始化和销毁方法 * * 构造(对象创建) * 单例:容器启动时创建对象 * 多实例:每次获取时创建容器对象 * BeanPostProcessor.PostProcessorBeforeInitialization * 初始化: * 对象创建完成,并赋值好,调用初始化方法。。。 * BeanPostProcessor.PostProcessorAfterInitialization * 销毁: * 单实例:容器关闭时候,进行销毁 * 多实例:容器不会管理这个bean;容器不会调用销毁方法
    1)、指定初始化和销毁方法
    // 基于配置文件的方式scope=“prototype” init-method="" destroy-method=""通过@Bean指定init-method 和 destroy-method; @Bean(initMethod = "init",destroyMethod = "destory") public Car car(){ return new Car(); } public class Car { public Car(){ System.out.println("car constructor...."); } public void init(){ System.out.println("car iit....."); } public void destory(){ System.out.println("car destory...."); } }
    2)、通过让bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)
    @Component public class Cat implements InitializingBean, DisposableBean { public Cat() { System.out.println("cat constructor...."); } public void destroy() throws Exception { System.out.println("cat .... destroy..."); } public void afterPropertiesSet() throws Exception { System.out.println("cat..afterPropertiesSet..."); } }
    3)、可以使用JSR250:

    @PostConstruct :在bean创建完成并且属性赋值完成,执行初始化

    @PreDestroy :在容器销毁之前通知我们进行清理工作

    @Component public class Dog { public Dog(){ System.out.println("Dog constructor..."); } //对象创建并赋值之后调用 @PostConstruct public void init(){ System.out.println("Dog...PostConstruct...."); } //在容器移除之前调用 @PreDestroy public void detory(){ System.out.println("Dog ....PreDestroy"); } }
    4)、BeanPostProcessor:bean的后置处理器;

    在bean的初始化前后进行一些处理工作:

    PostProcessorBeforeInitialization:在初始化之前工作

    PostProcessorAfterInitialization: 在初始化之后

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

    属性赋值@Value

    //使用@Value赋值 //1、基本数值 //2、可以写SpEL:#{} //3、可以写${}取出配置文件【properties】中的值(在运行环境变量中的值) @Value("张三") private String name; @Value("#{20-2}") private Integer age; @Value("${person.nickName}") private String nickName; person.nickName=小张三 //配置类中 //使用@PropertySource读取外部配置文件中的K/V保存到运行环境中;加载玩外部的配置文件以后使用${}取出配置文件的值 @PropertySource({"classpath:/person.properties"})
    Processed: 0.009, SQL: 9