spring 常用注解

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"})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值