组件扫描:
Spring能够从classpath自动扫描,查找特定注解的组件(Bean类)。
注解配置原理:
标注Bean类的注解,然后在xml配置文件中配置扫描的路径,就可以将标识注解的Bean交给IOC容器管理。
有四种特定组件:
@Component 基本注解,标识受Spring管理的组件
@Repository 标识持久层
@Service 标识业务层组件
@Controller 标识表现层组件
注意:
其实这些注解没有硬性要求,只是约定俗成而已的。
就算你给持久层标识@Component也没毛病
对于扫描到的组件,Spring有默认的命名策略,一般都是第一个字母小写,其他一样。
也可以在注解中通过value属性值标识组件的名称。即从容器中获取Bean组件的类名。
举例:
使用注解给Bean类进行注释,包括通过value重命名类名。
package one.two;
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
public void print(){
System.out.println("我是Component");
}
}
import org.springframework.stereotype.Controller;
@Controller
public class MyController {
public void print(){
System.out.println("我是Controller");
}
}
@Repository
public class MyRespository {
public void print(){
System.out.println("我是Respository");
}
}
@Service
public class MyService {
public void print(){
System.out.println("我是Service");
}
}
package one;
public interface Mytest {
void print();
}
import org.springframework.stereotype.Component;
@Component(value = "test")
public class MytestImpl implements Mytest{
@Override
public void print() {
System.out.println("我是MytestImpl");
}
}
xml文件也需要配置扫描:
context:component-scan可以指定Spring IOC容器要扫描的包
<context:component-scan base-package="one"></context:component-scan>
测试:
public class Main {
public static void main(String[] args) throws SQLException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
MyComponent one = (MyComponent) applicationContext.getBean("myComponent");
System.out.println(one);
MyController two = (MyController) applicationContext.getBean("myController");
System.out.println(two);
MyRespository three = (MyRespository) applicationContext.getBean("myRespository");
System.out.println(three);
MyService four = (MyService) applicationContext.getBean("myService");
System.out.println(four);
MytestImpl five = (MytestImpl) applicationContext.getBean("test");
System.out.println(five);
}
}
输出:
one.two.MyComponent@3439f68d
one.two.MyController@dbd940d
one.two.MyRespository@71d15f18
one.two.MyService@17695df3
one.MytestImpl@6c9f5c0d
context:component-scan可以指定Spring IOC容器要扫描的包
注意四个属性:
第一个:base-package:
指定需要扫描的基类包,会扫描该包以及其子包中的所有类,当需要扫描多个包的时候可以使用逗号分隔。
第二个:resource-pattern可以扫描特定的类 而非基包下的所有类: 在扫描base-package包的范围下。
<context:component-scan base-package="one" resource-pattern=
"two/*.class"></context:component-scan>
意思就是:通过注解,只能将one包下的two文件下所有的class文件加入到IOC容器中。
第三个:<context:include-filter>
:包含指定的组件
第四个:<context:exclude-filter>
:排除指定的组件 该子节点需要use-default-filters配合使用
type属性常用:
annotation:根据组件的类型
assignable:根据组件类的类名
注意:
context:component-scan可以包含多个
<context:include-filter>
和<context:exclude-filter>
annotation:根据组件的类型:
只要没有注解是Service的都可以加入到IOC容器中:
<context:component-scan base-package="one">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"></context:exclude-filter>
</context:component-scan>
只要注解是Service的都可以加入到IOC容器中,其他的不行:
<context:component-scan base-package="one" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"></context:include-filter>
</context:component-scan>
注意:
use-default-filters
属性默认是true 只针对context:include-filter标签,因为默认即使context:include-filter标签指定了范围,但是use-default-filters=true 则还是将基包下的所有注解组件类都加入到IOC中,只有指定false后 context:include-filter标签指定范围的才有效
assignable:根据组件类的类名
只要组件类全类名是one.Mytest或者实现该接口的实现类都可以加入到IOC容器中,其他的不行:
<context:component-scan base-package="one" use-default-filters="false">
<context:include-filter type="assignable" expression="one.MytestImpl"></context:include-filter>
</context:component-scan>
刚好和上面的相反
<context:component-scan base-package="one">
<context:exclude-filter type="assignable" expression="one.Mytest"></context:exclude-filter>
</context:component-scan>