spring注解

@Configuration

类似之前通过xml配置信息。

public class MainTest {

    public static void main(String[] args) {

        // 加载配置类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = applicationContext.getBean(Person.class);
        System.out.println(person);

        // bean默认名称是方法名为bean的名称,没找到抛异常。@Bean(value="")优先级高于方法名
        // Person person1 = (Person) applicationContext.getBean("person");
        // System.out.println(person1);

        Person person1 = (Person) applicationContext.getBean("person1");
        System.out.println(person1);

        // 两个条件满足情况下才能找到
        // Person person2 = (Person)applicationContext.getBean("person", Person.class);
        // System.out.println(person2);

        Person person3 = (Person)applicationContext.getBean("person1", Person.class);
        System.out.println(person3);
    }
}
@Configuration
public class MainConfig {

    @Bean
    public Person person1() {
        return new Person(1,"罗超群");
    }

}

@ComponentScan

扫描指定包并过滤指定的bean加载到容器。提供includeFilter和excludeFilter,过滤类型有:

  • FilterType.ANNOTATION 根据注解过滤
  • FilterType.ASSIGNABLE_TYPE 指定类
  • FilterType.CUSTOM 自定义过滤器,需要实现TypeFilter
  • FilterType.REGEX 正则匹配
@Configuration
@ComponentScan(value = "com.lcq.source.code.spring.annotation",
        includeFilters = {},
        excludeFilters = {
        // 过滤指定注解
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
        // 指定类过滤
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {LcqSourceCodeService.class}),
        // 自定义过滤
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}),
        // Lcq开头的类
        @ComponentScan.Filter(type = FilterType.REGEX, pattern = {"Lcq*"})
})
public class MainConfig {
    @Bean
    public Person person1() {
        return new Person(1,"罗超群");
    }
}
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
        // 获取当前类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类的资源(类的路径)
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("----" + className);
        if (className.contains("Lcq")) {
            return true;
        }
        return false;
    }
}
    public static void commpontScan() {

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        // 获取注入的bean,会将CommpontScan定义包下面所有加了Controller、Service、Commpont、Configuration等注解的类加载到容器
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName:beanNames) {
            System.out.println(beanName);
        }
    }

    public static void main(String[] args) {
        // configuration();

        commpontScan();
    }

@Scope

bean的作用域,有:

  • singleton 单实例(默认),ioc启动的时候会调用方法创建对象放到容器中,以后每次调用都从容器中获取实例
  • prototype 多实例,IOC启动的时候不会调用方法创建对象放到容器中,每次获取的时候才会创建
  • request 同一次请求创建一个实例
  • session 同一个session创建一个实例
@Configuration
@ComponentScan(value = "com.lcq.source.code.spring.annotation",
        includeFilters = {},
        excludeFilters = {
        // 过滤指定注解
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
        // 指定类过滤
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {LcqSourceCodeService.class}),
        // 自定义过滤
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}),
        // Lcq开头的类
        @ComponentScan.Filter(type = FilterType.REGEX, pattern = {"Lcq*"})
})
public class MainConfig {
    @Scope(value = "prototype")
    @Bean
    public Person person1() {
        System.out.println("#####给容器中添加Person");
        return new Person(1,"罗超群");
    }
}
public static void scope() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person1 = applicationContext.getBean(Person.class);
        Person person2 = applicationContext.getBean(Person.class);
        System.out.println(person1 == person2);
    }

    public static void main(String[] args) {
        // configuration();
        // commpontScan();
        scope();
    }
#####给容器中添加Person
#####给容器中添加Person
false

@Lazy

单实例容器启动会创建,懒加载可以让bean第一次使用的时候创建

@Conditional

根据条件判断是否加载bean,自定义的类需要继承Condition

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String osName = environment.getProperty("os.name");
        if (osName.contains("windows")) {
            return false;
        }
        return true;
    }
}

@Import

自己定义的类可以用@Service等注解
@Bean可以引用别人写的类。
@Import快速导入一个组件

@ImportSelector

自定义选择要导入的类,需要继承ImportSelector,返回值为类路径+类名的数。
可以使用ImportBeanDefinitionRegistrar:

public class ImportBeanRegister implements ImportBeanDefinitionRegistrar {
   @Override
   public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
       BeanDefinition beanDefinition = new RootBeanDefinition(House.class);
       beanDefinitionRegistry.registerBeanDefinition("house", beanDefinition);
   }
}

也可以通过FactoryBean定义bean,打印容器中的实例并不是factoryBean,而是factoryBean里定义的繁星,如果要获取factoryBean本身需要使用&+beanName

public class LcqFactoryBean implements FactoryBean<Child> {
    @Override
    public Child getObject() throws Exception {
        return new Child("yang");
    }
    @Override
    public Class<?> getObjectType() {
        return Child.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}
 public static void factoryBean() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Object objInstance = applicationContext.getBean("lcqFactoryBean");
        // class com.lcq.source.code.spring.annotation.bean.Child
        System.out.println(objInstance.getClass());
        Object objInstance2 = applicationContext.getBean("&lcqFactoryBean");
        // class com.lcq.source.code.spring.annotation.factoryBean.LcqFactoryBean
        System.out.println(objInstance2.getClass());
    }

@Bean

定义bean,提供initMethod和destroy方法,分别在初始化的时候和销毁的时候执行。如果是单实例,初始化方法在容器启动时候执行,容器关闭的时候会destroy;如果是多实例,获取这个bean时执行,容器关闭并不会调用destroy。除了initMethod和destroy方法,想要初始化和销毁还可以通过InitializingBean和DisposableBean。

@Configuration
public class MainConfigOfLifeCycle {
    @Bean(initMethod = "initCar", destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }
}

@PostConstruct

bean创建完成并且属性赋值完成执行

@PreDestroy

bean销毁之前执行

Bean实现BeanPostProcessor可以在bean初始化之前和初始化之后执行业务。

@Autowire

按类型自动装配

@Primary 没有使用Qualifier的情况下优先装配

@Qualifier 如果同一个类型的Bean定义了多个的情况下,可以根据名称使用哪个bean

@Resource 按名称自动装配,jdk里的注解

@Inject 自动装配,注解里面没有属性。需要导入javax.inject包

AOP

  • @Aspect 定义切面
  • @Pointcut 定义作用点
  • @Before 作用点执行前
  • @After 作用点执行后
  • @AfterReturning 返回时候执行
  • @AfterThrowing 抛异常时执行
  • @Around 环绕,可以修改返回值
  • @EnableAspectJAutoProxy 表示可以用aop
@Component
public class MathCalculator {
    public Integer add(int i,int j) {
        System.out.println("div运算进行中,i="+i+",j="+j);
        // throw new NullPointerException();
        return i+j;
    }
}
@Aspect
public class LogAspects {
    @Pointcut("execution(public Integer com.lcq.source.code.spring.annotation.aop.MathCalculator.*(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        System.out.println("运算开始"+joinPoint.getArgs()
                +","+joinPoint.getKind()
                +","+joinPoint.getSignature()
                +","+joinPoint.getSourceLocation()
                +","+joinPoint.getStaticPart()
                +","+joinPoint.getTarget()
                +","+joinPoint.getThis()
        );
    }
    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint) {
        System.out.println("运算结束"+joinPoint.getArgs()
                +","+joinPoint.getKind()
                +","+joinPoint.getSignature()
                +","+joinPoint.getSourceLocation()
                +","+joinPoint.getStaticPart()
                +","+joinPoint.getTarget()
                +","+joinPoint.getThis()
        );
    }
    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn(Object result) {
        System.out.println("运算正常返回,result="+result);
    }
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception){
        System.out.println("运算异常,exception="+exception);
    }
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        Object obj = joinPoint.proceed();
        // 修改返回值
        obj = 10;
        return obj;
    }
}
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
    @Bean
    public MathCalculator calculator() {
        return new MathCalculator();
    }
    @Bean
    public LogAspects logAspects() {
        return new LogAspects();
    }
}

执行结果:

运算开始[Ljava.lang.Object;@4d5d943d,method-execution,Integer com.lcq.source.code.spring.annotation.aop.MathCalculator.add(int,int),org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@3270d194,execution(Integer com.lcq.source.code.spring.annotation.aop.MathCalculator.add(int,int)),com.lcq.source.code.spring.annotation.aop.MathCalculator@235834f2,com.lcq.source.code.spring.annotation.aop.MathCalculator@235834f2
div运算进行中,i=1,j=2
运算结束[Ljava.lang.Object;@4d5d943d,method-execution,Integer com.lcq.source.code.spring.annotation.aop.MathCalculator.add(int,int),org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@3270d194,execution(Integer com.lcq.source.code.spring.annotation.aop.MathCalculator.add(int,int)),com.lcq.source.code.spring.annotation.aop.MathCalculator@235834f2,com.lcq.source.code.spring.annotation.aop.MathCalculator@235834f2
运算正常返回,result=10

关键类:

  • BeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • ApplicationContextAwareProcessor 判断类是实现了哪个Aware(EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware等),先把bean转成对应的Aware并调用对应的set方法赋值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352