文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

@ComponentScan在spring中无效的原因分析以及解决方法

2023-06-25 13:19

关注

这篇文章将为大家详细讲解有关@ComponentScan在spring中无效的原因分析以及解决方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

@ComponentScan在spring中无效

在我实现第一个spring AOP程序的时候,我按照主流的推荐,采用注解@ComponentScan @Aspect @Before 来实现一个切面。

让我十分纳闷的是。 我的程序始终无法正确调用到通知。而且我的通知和主流的毫无差别。代码如下:

通知类,其中定义了切面:

package com.bfytech.spring_8_bean3; import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component; @Aspect@Componentpublic class Advice {  @Before("execution(* com.bfytech.spring_8_bean3.Person.getName(..))") public void logBeforeFunction() {  System.out.println("function begin"); } @After("execution(* com.bfytech.spring_8_bean3.Person.*(..))") public void logAfterFunction() {  System.out.println("function end"); }}

业务类:

package com.bfytech.spring_8_bean3; import org.springframework.stereotype.Component; @Componentpublic class Person { private String name; private int age; public String getName() {  System.out.println("getName...");  return name; } public void setName(String name) {  this.name = name;  System.out.println("setName..."); } public int getAge() {  System.out.println("getAge...");  return age; } public void setAge(int age) {  System.out.println("setAge...");  this.age = age; } }

Bean配置类:

package com.bfytech.spring_8_bean3; import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration@EnableAspectJAutoProxy@ComponentScanpublic class BeanConfig {  @Bean public Advice advice() {  return new Advice(); }}

AppicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:p="http://www.springframework.org/schema/p"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:util="http://www.springframework.org/schema/util"    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"></beans>

最后的调用类App

package com.bfytech.spring_8_bean3; import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext; public class App {    public static void main( String[] args )    {        System.out.println( "Hello World!" );                ApplicationContext context = new FileSystemXmlApplicationContext("ApplicationContext.xml");        Person person = (Person) context.getBean(Person.class);          person.setName("Tony");          person.setAge(88);          System.out.println(person.getName());          System.out.println(person.getAge());    }}

郁闷之余。做了大量尝试,后来发现在ApplicationContext.xml中添加如下行:

<context:component-scan base-package="com.bfytech.spring_8_bean3"></context:component-scan>

之后可以正常把AOP启动起来。

查了大量资料之后,找到了原因

原来很多资料中把xml配置和注解配置混淆在一起了!

当你采用xml配置的时候,则ApplicationContext.xml的内容会生效。但是前提是你需要采用FileSystemXmlApplicationContext或者ClassPathXmlApplicationContext去读取这个xml,配置才会生效!同时@ComponentScan会被忽略!

而当你采用注解配置的时候,则你应该使用AnnotationConfigApplicationContext来加载,这时配置类的中的@ComponentScan就会生效。

修改代码App.java为

package com.bfytech.spring_8_bean3; import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext; public class App {    public static void main( String[] args )    {        System.out.println( "Hello World!" );             ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);        Person person = (Person) context.getBean(Person.class);                   person.setName("Tony");          person.setAge(88);          System.out.println(person.getName());          System.out.println(person.getAge());    }}

运行结果正常了!

顺便说,还有一个坑。execution表达式因为没有编译时检查,任何标点符号的错误也会在运行时忽略(??我很纳闷,为什么不抛异常),所以需要反复检查。比如说下面的表达式,你觉得有错么?

@Before("execution(* com.bfytech.spring_8_bean3.*.*(**))")

这个表达式是错误的,因为(**)应该是(..).而运行时这个不会报任何错误。但是切片的代码不会运行.....

@Component和@ComponentScan常规理解

@Component和@ComponentScan的联系

@Component 这个注解的作用是把我们写的bean注入到容器中,以供使用。

@ComponentScan 注解的作用则是扫描包中的bean(比如:Spring不知道你定义了某个bean除非它知道从哪里可以找到这个bean,ComponentScan做的事情就是告诉Spring从哪里找到bean),由你来定义哪些包需要被扫描。

一旦你指定了,Spring将会将在被指定的包及其下级包中寻找bean,这两个注解进行配合使用。

@SpringBootApplication和@ComponentScan,扫描包的区别

如果你的其他包都在使用了@SpringBootApplication注解的main app所在的包及其下级包,则你什么都不用做,SpringBoot会自动帮你把其他包都扫描了如果你有一些bean所在的包,不在main app的包及其下级包,那么你需要手动加上@ComponentScan注解并指定那个bean所在的包。

关于@ComponentScan在spring中无效的原因分析以及解决方法就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯