@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.*.*(**))")

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

猜你喜欢

转载自blog.csdn.net/CandCplus/article/details/81564513