@ComponentScan在spring中無(wú)效的原因分析及解決方案
@ComponentScan在spring中無(wú)效
在我實(shí)現(xiàn)第一個(gè)spring AOP程序的時(shí)候,我按照主流的推薦,采用注解@ComponentScan @Aspect @Before 來(lái)實(shí)現(xiàn)一個(gè)切面。
讓我十分納悶的是。 我的程序始終無(wú)法正確調(diào)用到通知。而且我的通知和主流的毫無(wú)差別。代碼如下:
通知類,其中定義了切面:
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 @Component public 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"); } }
業(yè)務(wù)類:
package com.bfytech.spring_8_bean3; import org.springframework.stereotype.Component; @Component public 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 @ComponentScan public 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>
最后的調(diào)用類App
package com.bfytech.spring_8_bean3; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; /** * Hello world! * */ 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()); } }
郁悶之余。做了大量嘗試,后來(lái)發(fā)現(xiàn)在ApplicationContext.xml中添加如下行:
<context:component-scan base-package="com.bfytech.spring_8_bean3"></context:component-scan>
之后可以正常把AOP啟動(dòng)起來(lái)。
查了大量資料之后,找到了原因
原來(lái)很多資料中把xml配置和注解配置混淆在一起了!
當(dāng)你采用xml配置的時(shí)候,則ApplicationContext.xml的內(nèi)容會(huì)生效。但是前提是你需要采用FileSystemXmlApplicationContext或者ClassPathXmlApplicationContext去讀取這個(gè)xml,配置才會(huì)生效!同時(shí)@ComponentScan會(huì)被忽略!
而當(dāng)你采用注解配置的時(shí)候,則你應(yīng)該使用AnnotationConfigApplicationContext來(lái)加載,這時(shí)配置類的中的@ComponentScan就會(huì)生效。
修改代碼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; /** * Hello world! * */ 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()); } }
運(yùn)行結(jié)果正常了!
順便說(shuō),還有一個(gè)坑。execution表達(dá)式因?yàn)闆](méi)有編譯時(shí)檢查,任何標(biāo)點(diǎn)符號(hào)的錯(cuò)誤也會(huì)在運(yùn)行時(shí)忽略(??我很納悶,為什么不拋異常),所以需要反復(fù)檢查。比如說(shuō)下面的表達(dá)式,你覺(jué)得有錯(cuò)么?
@Before("execution(* com.bfytech.spring_8_bean3.*.*(**))")
這個(gè)表達(dá)式是錯(cuò)誤的,因?yàn)?**)應(yīng)該是(..).而運(yùn)行時(shí)這個(gè)不會(huì)報(bào)任何錯(cuò)誤。但是切片的代碼不會(huì)運(yùn)行.....
@Component和@ComponentScan常規(guī)理解
@Component和@ComponentScan的聯(lián)系
@Component 這個(gè)注解的作用是把我們寫(xiě)的bean注入到容器中,以供使用。
@ComponentScan 注解的作用則是掃描包中的bean(比如:Spring不知道你定義了某個(gè)bean除非它知道從哪里可以找到這個(gè)bean,ComponentScan做的事情就是告訴Spring從哪里找到bean),由你來(lái)定義哪些包需要被掃描。
一旦你指定了,Spring將會(huì)將在被指定的包及其下級(jí)包中尋找bean,這兩個(gè)注解進(jìn)行配合使用。
@SpringBootApplication和@ComponentScan,掃描包的區(qū)別
如果你的其他包都在使用了@SpringBootApplication注解的main app所在的包及其下級(jí)包,則你什么都不用做,SpringBoot會(huì)自動(dòng)幫你把其他包都掃描了如果你有一些bean所在的包,不在main app的包及其下級(jí)包,那么你需要手動(dòng)加上@ComponentScan注解并指定那個(gè)bean所在的包。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot如何使用applicationContext.xml配置文件
- 集成apollo動(dòng)態(tài)日志取締logback-spring.xml配置
- SpringBoot如何讀取xml配置bean(@ImportResource)
- SpringMVC xml文件路徑在web.xml中的配置方式
- 基于spring-mvc.xml和application-context.xml的配置與深入理解
- SpringBoot默認(rèn)包掃描機(jī)制及@ComponentScan指定掃描路徑詳解
- SpringBoot中@ComponentScan的使用詳解
- Spring?component-scan?XML配置與@ComponentScan注解配置
相關(guān)文章
解決java.lang.ClassCastException的java類型轉(zhuǎn)換異常的問(wèn)題
這篇文章主要介紹了解決java.lang.ClassCastException的java類型轉(zhuǎn)換異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09idea神級(jí)插件及如何安裝Bito插件【Bito-ChatGPT】
這篇文章主要介紹了介紹一款idea神級(jí)插件【Bito-ChatGPT】,Bito插件的強(qiáng)大之處在于它可以幫助開(kāi)發(fā)人員更快地提交代碼,同時(shí)還提供了一些有用的功能,如自動(dòng)補(bǔ)全提交信息、快速查看歷史記錄等,需要的朋友可以參考下2023-04-04Spring boot通過(guò)切面,實(shí)現(xiàn)超靈活的注解式數(shù)據(jù)校驗(yàn)過(guò)程
這篇文章主要介紹了Spring boot通過(guò)切面,實(shí)現(xiàn)超靈活的注解式數(shù)據(jù)校驗(yàn)過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12在SpringBoot中靜態(tài)資源訪問(wèn)方法
這篇文章給大家介紹了在SpringBoot中靜態(tài)資源訪問(wèn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-11-11