Spring注解驱动开发的学习

学习路线

在这里插入图片描述

1.容器

spring认为所有的组件都应该放在容器中,通过容器的自动装配来使用
基于注解开发时 配置类就等同于之前使用的配置文件
@Configuration 表示这是一个配置类

@Target({ElementType.TYPE})//只能标记在类上
@Retention(RetentionPolicy.RUNTIME)//储存
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

1.1bean注解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})//标记在方法和注解类上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")//标记用于表示bean的id
    String[] name() default {};

    /** @deprecated */
    @Deprecated
    Autowire autowire() default Autowire.NO;

    boolean autowireCandidate() default true;

    String initMethod() default "";

    String destroyMethod() default "(inferred)";
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
/**
 * 这是一个配置类
 */
public class MainConfig {
    @Bean
    /**
     * 给容器注册一个bean
     * 返回值为bean的类
     * id默认是用方法名做id
     */
    public person person(){
        return new person();
    }
}


import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class mainTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        person bean = applicationContext.getBean(person.class);
        System.out.println(bean);
    }
}

在这里插入图片描述

@componentScan包扫描注解

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})//标记在类上
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")//指定扫描的包 可以是数组  也就是指定扫描的多个包
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

							//ComponentScan.Filter是注解写在下面
    ComponentScan.Filter[] includeFilters() default {};//扫描时包含哪些注解

    ComponentScan.Filter[] excludeFilters() default {};//扫描时排除那些注解

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;//按照注解规则,这是一个枚举类

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}


public enum FilterType {
    ANNOTATION,//按照注解类
    ASSIGNABLE_TYPE,//按照指定的类 如{BookService.class}这样写
    ASPECTJ,//
    REGEX,//按照正则表达式
    CUSTOM;//自定义规则,要写一个TypeFilter实现类

    private FilterType() {
    }
}

@ComponentScan(value = {},includeFilters = {
        @ComponentScan.Filter(Type= FilterType.ANNOTATION,classes = {Service.class, Controller.class})
})
/**
 * 标记包扫描
 * value里表示的指定的包
 * includeFilters扫描策略,Type= FilterType.ANNOTATION按照注解进行包含
 * 用于扫描指定包下的spring注解如:@service @component @controller @reporsity等
 * 标记在类上
 */

Scope注解设置组件作用域


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
    @AliasFor("scopeName")
    String value() default "";

    @AliasFor("value")
    String scopeName() default "";

    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
@Scope(value = "Prototype")//""singleton原型
public person person(){
    return new person();
}

@lazy 设置bean懒加载

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

标记在方法或者类上用于表示被标记的组件开启懒加载
也就是不会再创建ioc容器时创建bean而是在被调用时创建

@conditional 按条件注册bean

conditional注解使用时传入的value是一个condition对象
我们要自己编写实现了condition接口的具体对象

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
public class MyCondition implements Condition {
    @Override
    /**
     * ConditionContext:判断条件可以使用的上下文环境
     * AnnotatedTypeMetadata:当前标注了condition注解的注释信息
     */
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //bean工厂
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义注册器
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //
        String property = environment.getProperty("os.name");

        if (property.contains("Windows")){

            return  true;
        }

        return false;
    }
}


//具体使用时
@Bean("person2")
@Conditional({MyCondition.class})
public person person2(){
    return new person();
}

@import 给容器快速导入组件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    Class<?>[] value();
}~
1.第一种使用方法
@Import(person.class)
直接标记在类上
注册的类的id为类的全类名
@Import(person.class)
public class MainConfig {~
2.通过ImportSelector进行注册
需要自己创建一个实现了ImportSelector接口的对象传入到import的value中
public class MyImportSelector implements ImportSelector {
    @Override
    //返回值就是要导入到容器里的类的全类名
    //annotationMetadata可以获取当前类所标的所有的注解的注解的信息
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //string数组里放的时要实现类的全类名
        return new String[]{"person"};
    }
}~

@Import(MyImportSelector.class)
public class MainConfig {~
3.通过ImportBeanDefinitionRegistrar对象注册

创建一个ImportBeanDefinitionRegistrar~
接口的实现类传入到import的value属性值中

public class BeanDefination implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata 被标记类的注释信息
     * @param registry  注册bean定义
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        registry.registerBeanDefinition("person",new RootBeanDefinition(person.class));
    }
}~

@Import(BeanDefination.class)
public class MainConfig {~
~

@FactoryBean注册组件

创建一个实现了factorybean接口的实现类
并通过@bean的方式存入容器,方法的名称就是类的id

public class personTest implements FactoryBean {
    @Override
    //返回单个实现类
    public Object getObject() throws Exception {
        return new person();
    }

    @Override
    //实现类的类对象数组
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    //判断是否为单例
    public boolean isSingleton() {
        return false;
    }
}~


//使用时
@Bean
public FactoryBean factoryBean(){
    return new personTest();
}~

设置bean的生命周期

在这里插入图片描述

外部资源文件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
    String name() default "";

    String[] value();//配置文件的路径从class path开始可以一次导入多个

    boolean ignoreResourceNotFound() default false;

    String encoding() default "";

    Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
~

取出配置文件的属性值时通过value(${…})

自动装配

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;//这个属性可以设置是否必须注入组件如果为			 true那么
}~

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
    String value() default "";
}~

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

/**

  • 自动装配:
  •  spring利用依赖注入自动存入相应的组件
    
  • 注解:
  •  @Autowired:自动注入(优先按照类型找到并赋值,如果同时有多个相应类型的组件
    
  •              就对属性名作为组件id到容器内查找组件并赋值)
    
  •  @Qualifier:按照指定的id装入,如果容器中没有指定id的组件,那么会报出异常
    
  •  @Primary:这个不能与Qualifier一起使用,他的作用是对某个组件指定首选,让这个组件优先级最高
    

*/~

在这里插入图片描述

在这里插入图片描述

Aware接口

Profile根据环境注册bean

在这里插入图片描述
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();//环境标识
}~
在这里插入图片描述

@PropertySource({"classpath:db.properties"})
public class MainConfig {

    @Profile("test")
    @Bean("caohao")
    public person person1(){
        person person = new person();
        person.setName("test");
        return person;
    }

    @Profile("Dev")
    @Bean("caohao")
    public person person2(){
        person person = new person();
        person.setName("dev");
        return person;
    }



public class mainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.getEnvironment().setActiveProfiles("Dev");
        applicationContext.register(MainConfig.class);
        applicationContext.refresh();
        person caohao = (person) applicationContext.getBean("caohao");
        System.out.println(caohao.getName());
原创文章 65 获赞 11 访问量 2070

猜你喜欢

转载自blog.csdn.net/qq_43147121/article/details/104208141