@ComponentScan在spring中無效的原因分析及解決方案
@ComponentScan在spring中無效
在我實現(xiàn)第一個spring AOP程序的時候,我按照主流的推薦,采用注解@ComponentScan @Aspect @Before 來實現(xiàn)一個切面。
讓我十分納悶的是。 我的程序始終無法正確調用到通知。而且我的通知和主流的毫無差別。代碼如下:
通知類,其中定義了切面:
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è)務類:
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());
}
}
郁悶之余。做了大量嘗試,后來發(fā)現(xiàn)在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和@ComponentScan常規(guī)理解
@Component和@ComponentScan的聯(lián)系
@Component 這個注解的作用是把我們寫的bean注入到容器中,以供使用。
@ComponentScan 注解的作用則是掃描包中的bean(比如:Spring不知道你定義了某個bean除非它知道從哪里可以找到這個bean,ComponentScan做的事情就是告訴Spring從哪里找到bean),由你來定義哪些包需要被掃描。
一旦你指定了,Spring將會將在被指定的包及其下級包中尋找bean,這兩個注解進行配合使用。
@SpringBootApplication和@ComponentScan,掃描包的區(qū)別
如果你的其他包都在使用了@SpringBootApplication注解的main app所在的包及其下級包,則你什么都不用做,SpringBoot會自動幫你把其他包都掃描了如果你有一些bean所在的包,不在main app的包及其下級包,那么你需要手動加上@ComponentScan注解并指定那個bean所在的包。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- SpringBoot如何使用applicationContext.xml配置文件
- 集成apollo動態(tài)日志取締logback-spring.xml配置
- SpringBoot如何讀取xml配置bean(@ImportResource)
- SpringMVC xml文件路徑在web.xml中的配置方式
- 基于spring-mvc.xml和application-context.xml的配置與深入理解
- SpringBoot默認包掃描機制及@ComponentScan指定掃描路徑詳解
- SpringBoot中@ComponentScan的使用詳解
- Spring?component-scan?XML配置與@ComponentScan注解配置
相關文章
解決java.lang.ClassCastException的java類型轉換異常的問題
這篇文章主要介紹了解決java.lang.ClassCastException的java類型轉換異常的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
idea神級插件及如何安裝Bito插件【Bito-ChatGPT】
這篇文章主要介紹了介紹一款idea神級插件【Bito-ChatGPT】,Bito插件的強大之處在于它可以幫助開發(fā)人員更快地提交代碼,同時還提供了一些有用的功能,如自動補全提交信息、快速查看歷史記錄等,需要的朋友可以參考下2023-04-04
Spring boot通過切面,實現(xiàn)超靈活的注解式數(shù)據(jù)校驗過程
這篇文章主要介紹了Spring boot通過切面,實現(xiàn)超靈活的注解式數(shù)據(jù)校驗過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12

