spring注解式开发

一、@Configuration

声明一个类相当于配置类似于xml的配置文件,声明一个或者多个@Bean方法,并由spring容器管理,以便于在运行中为这些bean生成BeanDefinition和服务请求。

@Configuration
//包扫描
@ComponentScan(value = "com.alibaba")
})
public class MyConfig {
    //如果Bean标签里不写值 bean在spring容器里的key就是方法名
    @Bean(value = "book")
    public TestBook testBook() {
        return new TestBook("三国演义",128);
    }
}

简单的看下configuration的内部实现

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration { ... }

可以看到@Component组件注解,意味着也会注册为bean,其内部也可以依赖导入。(例如: @Autowired、@Inject、@Scope等)

@Configuration可理解为用spring的时候xml里面的标签,作用为:配置spring容器(应用上下文)

   @Bean可理解为用spring的时候xml里面的<bean>标签

**@Controller:**用于标注控制层服务。

**@Repository:**用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件。

**@Service:**用于标注业务逻辑层服务,主要用来进行业务的逻辑处理,注入DAO。这种bean默认是单例的,如果想改变,可以使用@Service(“beanName”) 、@Scope(“prototype”)来改变。

**@Component:**把普通的类实例化到spring容器中,相当于配置文件中的 。泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Repository、@Services等的时候),我们就可以使用@Component来标注这个类。

@ComponentScan(value="com.xxx",excluddFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})})

@ComponentScan(value="com.xxx",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class},userDefaultFilters=false)})

@Target:注解的作用目标

@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包

@ComponentScan
//value:扫描指定的包

//excluddFilters = Filter[] 指定排除那些组件

// includeFilters = Filter[] //指定包含那些组件进行扫描 ,如果配置只包含扫描规则,则同时要配置userDefault-filters=false;禁用默认过滤规则;
userDefaultFilters=false 因为spring默认是全局扫描的 要配置成false

**@Filter注解**
@Filter(type=FilterType.ANNOTATION,classes={Controller.class},userDefaultFilters=false)

FilterType.ANNOTATION 按注解
FilterType.ASSIGNABLE_TYPE按照给定的类型
FilterType.CUSTOM 自定义过滤规则 (需要实现org.springframework.core.type.filter.TypeFilter接口)
excluddFilters 和includeFilters 根据过滤类返回的boolean值 进行过滤
等等 详细请看源码

@Scope 可以设置bean的作用范围

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

看源码可知可以作用在类上和方法上
作用范围:

COPE_PROTOTYPE  多实例的
SCOPE_SINGLETON  单实例的 是默认的
web.context.WebApplicationContext#SCOPE_REQUEST 基本不用
web.context.WebApplicationContext#SCOPE_SESSION  基本不用

@Lazy 懒加载
在开发中 可能不想在启动spring容器的时候就去加载bean,在getBean的时候再去加载Bean 所以就有了 懒加载

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {

关于该注解的作用范围可以看上面的@Target的作用范围

@Conditional 按条件给容器注册Bean
实现Condition接口并且实现里面的方法
该注解可以加在类上和方法上

public class TestConditional implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
   //ConditionContext  判断条件能使用的上下文环境
   //AnnotatedTypeMetadata  注释信息
        return false;
    }
}

//如果改实现类照中的方法 返回true就在容器中创建改bean如果为false则不创建
@Bean(value = “book”)
@Conditional(TestConditional.class)
public TestBook testBook() {
return new TestBook(“三国演义”,128);
}

@Import[快速给容器中导入一个组件]

1.@Import(要导入容器中的组件)加上这个注解和配置相关的参数之后,容器就会自动的注册这个组件,id默认是全类定名
格式@Import(XXX.class)

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

public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //当前类标注的注解信息 AnnotationMetadata
        return new String[]{"全类定名A","全类定名B"};
    }
}

3.ImportBeanDefinitionRegistrar:(手动向容器中添加bean)

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Dog.class);
        registry.registerBeanDefinition("Dog", rootBeanDefinition);
    }
}

里面会有两个参数:
**AnnotationMetadata:**当前类的注解信息
**BeanDefinitionRegistry:**BeanDefinition注册类 把所有需要添加到容器中的bean 调用BeanDefinitionRegistry.registerBeanDefinition(String var1, BeanDefinition var2)手动调用

通过spring提供的FactionBean(工厂Bean)
1、默认获取的是工厂bean调用getObject创建对象
2、要获取工厂Bean本身,我们要给id前面加一个&

Bean的生命周期
@Bean(initMethod=“xxx”,destroyMethod=“xxx”)
1、单例的bean的init方法是在 创建spring容器启动就执行了,destroy方法是在spring容器关闭的时候执行的
多例的bean在spring容器加载完毕的时候 不会执行init 方法,在获取bean的时候会执行init方法,即使spring容器关闭也不会执行destroy方法、只能手动调用。
2、实现InitializingBean(定义初始化逻辑)
DisposableBean(定义销毁逻辑)同时实现两个接口

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

3.BeanPostProcessor:后置处理器
实现BeanPostProcessor接口并且实现里面的方法

postProcessBeforeInitialization :在初始化方法前执行
postProcessAfterInitialization:在初始化方法之后执行

实现类上要加上@Component让其作为组件

@Value()
1.可以使用基本数值
2.可以使用Spring的EL表达式#{}
3.可以使用${}取出配置文件上的值(在运行环境变量里面 的值)配合@PropertySource(value=“配置文件的路径”)使用 这个注解式加载配置类上

@Autowired
1、 自动注入默认是按照类型去容器中找对应的组件
2、如果存在多个相同类型的组件bean 就会按照属性名作为组件id去容器中查找。 注:如果要指定组件可以用@Qualifier(要指定组件的id)
3、自动注入的时候可能这个组件在容器中并没有,如果没有的话 会报错,如果允许为空的话可以借助@Autowired(required = false) 这样自动装配的时候就不会报错了
4、@Primary 让spring在自动装配的时候。默认使用首选的bean,如果配合使用@Qualifer的话就会使用该注解标注的bean。@Primary就不生效了

@Autowired 作用范围:构造器,方法,参数,属性,都是从容器中获取参数组件的值。
1、标注在方法上:@Bean+方法参数,参数从容器中获取,默认是不写Autowired,效果是一样的,都能自动装配。
2、标注在构造器上,如果组件只有一个有参的构造器,这个有参的构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取。
3、放在参数位置。

@Resource
Spring还支持@Resouce(JSR250)和@Inject(JSR330)【Java规范标注】
@Resource可以和@Autowired一样完成自动装配,默认是按照组件名称进行的,不可以和@Qualifier和@Primary配合使用,也没有@Autowired(required = false)

@Inject需要导入javax.inject的包

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

其效果和@Autowired一样,只是不可以用Autowired的required = false这个。

AutowiredAnnotationBeanPostProcessor:以上三个都是通过该类完成解析自动装配。

自定义组件使用spring容器中的一些组件(ApplicationContextAwareProcessor,BeanFactory,XXX)

自定义的组件实现xxxAware;在创建对象的时候会调用接口规定的方法注入相关组件;Aware把Sring底层的一些组件注入到自定义的Bean中;
xxxAware功能使用的是xxxProcessor;
例如:ApplicationContextAware–>ApplicationContextAwareProcessor

@Profile:指定组件在某个环境下才能被注册到容器中,如果不指定(也就是不加这个注解)在任何环境下就能注册这个组件
在实际开发过程中,特别是大厂,都会有测试环境,预发环境,正式环境,以数据库为例:开发者不希望者这三套环境用同一个数据源,所以可以在三套数据源上加上这个注解,只有这个环境被激活了才能被注册到容器中。
默认值是 :default

@Configuration
@ComponentScan("com.baizhi.profile")
@Profile("test")
public class TestProfileConfig {

    @Profile("testDev")
    @Bean
    public TestProfile testDev(){
        return new TestProfile();
    }

    @Bean
    @Profile("testPro")
    public TestProfile testPro(){
        return new TestProfile();
    }
    @Profile("test")
    @Bean
    public TestProfile test(){
        return new TestProfile();
    }
}

配置的方式。代码层面的

//创建对象
 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
 //设置运行变量
applicationContext.getEnvironment().setActiveProfiles("test");
注册配置类
applicationContext.register(TestProfileConfig.class);
//刷新生成容器
applicationContext.refresh();

2、设置运行参数:
-Dspring.profiles.active=“xxxxx”

作者 纯手打的 如有 问题 请留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值