您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關@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 @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"); } }
業務類:
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>
最后的調用類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()); } }
郁悶之余。做了大量嘗試,后來發現在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; /** * 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()); } }
運行結果正常了!
順便說,還有一個坑。execution表達式因為沒有編譯時檢查,任何標點符號的錯誤也會在運行時忽略(??我很納悶,為什么不拋異常),所以需要反復檢查。比如說下面的表達式,你覺得有錯么?
@Before("execution(* com.bfytech.spring_8_bean3.*.*(**))")
這個表達式是錯誤的,因為(**)應該是(..).而運行時這個不會報任何錯誤。但是切片的代碼不會運行.....
@Component 這個注解的作用是把我們寫的bean注入到容器中,以供使用。
@ComponentScan 注解的作用則是掃描包中的bean(比如:Spring不知道你定義了某個bean除非它知道從哪里可以找到這個bean,ComponentScan做的事情就是告訴Spring從哪里找到bean),由你來定義哪些包需要被掃描。
一旦你指定了,Spring將會將在被指定的包及其下級包中尋找bean,這兩個注解進行配合使用。
如果你的其他包都在使用了@SpringBootApplication注解的main app所在的包及其下級包,則你什么都不用做,SpringBoot會自動幫你把其他包都掃描了如果你有一些bean所在的包,不在main app的包及其下級包,那么你需要手動加上@ComponentScan注解并指定那個bean所在的包。
關于@ComponentScan在spring中無效的原因分析以及解決方法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。