基于java的Bean配置的自动装配
从Spring3.0开始通过java注解定义Bean:
@Conmponent 一个通用注解,可用于任何Bean(下面三个为其子注解)
@Repository :注解持久化类
@Service:注解服务层类
@Controller:注解控制层类(通常在Spring MVC中使用)
其他注解:
@Required
@Autowired
@Qualifier
@Resource
元注解:一个简单的注解可以应用到另外一个注解(由Spring提供的可以作为自己代码的注解)
Spring可以检测到类并将其注册到上下文ApplicationContext中
类的自动检测:
<context:component-scanbase-package="com"/><!-- 扫描类的注解-->
<context:annotation-config></context:annotation-config><!--使用前者后不再使用这个,前者已经包含后者全部功能-->
过滤器进行自定义扫描:
类被发现并注册bean的条件:使用@Conmponent @Repository @Service@Controller注解或者使用@Conmponent自定义的注解
通过过滤器修改上面的行为:(regex通配符)
<context:component-scanbase-package="com"><!-- 扫描类的注解-->
<context:include-filtertype="regex"expression=".*Stub.*Repository"/>
<context:include-filtertype="annotation"expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
还可以使用use-default-filters=”false”禁用自动发现与注册
定义Bean:
Bean名称由BeanNameGenerator生成(@Conmponent @Repository @Service@Controller可以显式设置Bean)
示例一:工程结构图:
ComponentTest.java
package com.spring.Component;
import org.springframework.stereotype.Component;
/**
* Created by ruanjianlin on 2017/10/5.
*/
@Component("component")
public class ComponentTest {
}
(单元测试)ComponentTestTest.java(通过注解对bean进行命名)
package com.spring.Component;
import com.spring.Repository.RepositoryImpIements;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import static org.junit.Assert.*;
/**
* Created by ruanjianlin on 2017/10/6.
*/
public class ComponentTestTest {
@Test
public void testComponentAnnotation(){
ApplicationContext app=newFileSystemXmlApplicationContext("路径+Annotation-test.xml");
ComponentTest componentTest=(ComponentTest)app.getBean("component");
}
}
ControllerDemo.java
package com.spring.controller;
import org.springframework.stereotype.Controller;
/**
* Created by ruanjianlin on 2017/10/5.
*/
@Controller
public class ControllerDemo {
public voidexecute(){
System.out.println("Controller annotation test");
}
}
(单元测试)ControllerDemoTest.java
package com.spring.controller;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import static org.junit.Assert.*;
/**
* Created by ruanjianlin on 2017/10/6.
*/
public class ControllerDemoTest {
@Test
public voidexecute()throws Exception {
ApplicationContext app=newFileSystemXmlApplicationContext("自己的路径+Annotation-test.xml");
ControllerDemo con=( ControllerDemo)app.getBean("controllerDemo");
con.execute();
}
}
RepositoryInterface.java
package com.spring.Repository;
/**
* Created by ruanjianlin on 2017/10/5.
*/
public interface RepositoryInterface {
voidsave();
}
RepositoryImplements.java(实现上面的接口)
package com.spring.Repository;
import org.springframework.stereotype.Repository;
/**
* Created by ruanjianlin on 2017/10/5.
*/
@Repository
public class RepositoryImpIementsimplements RepositoryInterface {
public voidsave() {
System.out.println("Repository annotation test");
}
}
ServiceDemo,java
package com.spring.service;
import org.springframework.stereotype.Service;
/**
* Created by ruanjianlin on 2017/10/5.
*/
@Service
public class ServiceDemo {
public voidaddUser(){
System.out.println("service annotation test");
}
}
其他有关的junit测试代码请自己仿照上面的例子进行编写
Annotation-test.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scanbase-package="com.spring"><!-- 扫描类的注解 只扫描特定的文件-->
</context:component-scan>
</beans>
注:。若在类定义中添加注解时未指定Bean id则Spring将按照默认命名进行注册,名字是它的类名第一个字符小写 例如:ControllerDemo通过Controller注解注册时默认的注解名是controllerDemo,也可以自己指定
补充:
(1)通过resource-pattern指定扫描的资源
<context:component-scan base-package="com.spring"resource-pattern="Repository/*.class"><!-- 扫描类的注解 只扫描特定的文件-->
</context:component-scan>
运行结果:
controllerDemoTest:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'controllerDemo' is defined
Process finished with exit code -1
RepositoryImpIementsTest:
Process finished with exit code 0
由上面的运行结果可以判定resource-pattern作用即指定访问资源
排除特定的注解 exclude-filter expression输入排除的注解
<context:component-scanbase-package="package com.spring">
<context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
调用相关注解注册的Bean时产生的异常:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'repositoryImpIements' is defined
指定特定的注解 include-filter
<context:component-scanbase-package="package com.spring"use-default-filters="false">
<context:include-filtertype="annotation"expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
调用其指定的注解注册的Bean:
Process finished with exit code 0
调用无关的Bean:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'controllerDemo' is defined
use-default-filters默认为true扫描包下的所有注解
<context:include-filter>和<context:exclude-filter>子节点支持多种类型的过滤表达式(即type的取值):
类别 | 示例 | 说明 |
annotation | org.springframework.stereotype. xxAnnotation | 所有标注了XxxAnnotation的类,该类型采用目标类是否标注了某个注解进行过滤 |
assinable | com.spring.XxxService | 所有继承或扩展XxxService的类,该类型采用了目标类是否继承或扩展某个特定类进行过滤 |
aspectj | com.spring.*Service | 所有类名义Service结束的类及继承或扩展它们的类,该类型采用AspectJ表达式进行过滤 |
regex | com.spring.anno.* | 所有com.spring.anno包下的类。该类型采用正则表达式,根据类的类名进行过滤 |
custom | com.spring.XxxTypeFilter | 自定义过滤器,采用XxxTypeFilter通过代码的方式(自己建立的过滤器)定义过滤原则。该类必须实现org.springframework |
Regex使用示例:
<context:component-scanbase-package="com.spring"use-default-filters="false">
<context:include-filtertype="regex"expression="com.spring.Repository.*"/>
</context:component-scan>
assinable使用示例:
<context:component-scanbase-package="com.spring"use-default-filters="false">
<context:include-filtertype="assignable"expression="com.spring.Repository.RepositoryInterface"/>
</context:component-scan>
调用没有实现相关继承时控制台的输出:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'controllerDemo' is defined