使用annotation减少spring bean的配置

xiaoxiao2026-08-30  23

使用annotaion定义一个bean @Component 是一个通用注解,用于说明一个类是一个spring容器管理的类。 除此之外,还有@Controller , @Service , @Repository 是@Component的细化,这三个注解比@Component带有更多的语义,它们分别对应了表现层、服务层、持久层的类。 如果你只是用它们定义bean,你可以仅使用@Component,但是既然spring提供这些细化的注解,那肯定有使用它们的好处,不过在以下的例子中体现不出。定义了一个接口

package test1; interface  MovieFinder {     String getData(); }

定义一个实现

package test1; import org.springframework.stereotype.Repository; @Repository public   class  JpaMovieFinder implements MovieFinder {     @Override      public  String getData() {          return   "This is JpaMovieFinder implementation!" ;     } }

这里使用了注解@Repository,说明这是一个受spring容器管理的bean定义,这个注解没有指定bean的名字,默认为小写开头的类名,就是jpaMovieFinder,如果你要指定名字,可以这样写@Repository("myMovieFinder")。 这里也可以使用@Component这个注解,在这里例子中体现不出用@Repository的好处。 这里没有指定这个bean的scope,缺省是singleton,如果你要其他scope,可以使用注解@Scope

@Scope( "prototype" ) @Repository public   class  MovieFinderImpl implements MovieFinder {      // ... } spring扫描并注册注解的bean JpaMovieFinder只是添加了一个注解,这并不会自动被注册到spring容器中,我们需要告诉spring容器到那里去寻找这些bean。 配置如下: <?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-2.5.xsd            http: //www.springframework.org/schema/context            http: //www.springframework.org/schema/context/spring-context-2.5.xsd">                      <context:component-scan  base -package= "test1" />       </beans> <context:component-scan  base -package= "test1" />这个配置告诉spring容器到test1这个package下去扫描所有的类,从而找到被注解的类。 由于并不是test1下的所有的类都有注解,全部遍历效率不高,所以spring定义了过滤器用于减小扫描范围,这里为了简单起见没有使用。使用注解进行依赖注入 package test1; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public   class  SimpleMovieLister {          @Autowired      private  MovieFinder movieFinder;      public  String getData(String name) {          return   "Hi "  + name +  "! "  + movieFinder.getData();     }           public  MovieFinder getMovieFinder() {          return  movieFinder;     }      public   void  setMovieFinder(MovieFinder movieFinder) {          this .movieFinder = movieFinder;     } } SimpleMovieLister是一个服务类,它也使用了@Service注解为了bean,这个类用到了MovieFinder,为了注入这个类的实现,这里使用了注解 @Autowired ,spring容器会自动找到合适的bean注入进去。注意这里并没有指定被注入bean的名字,因为spring根据只发现了一个实现,那就是 jpaMovieFinder。后面,我们会看到有两个实现会怎样。 注意,上面代码使用@Autowired时, public   void  setMovieFinder(MovieFinder movieFinder) 这个方法是不需要的,你可以把它删除了试一试。如果你使用xml的配置方式,该方法必须存在。我这里保留该方法,是为了后面测试注解和xml配置混合使用的方式。 测试1 package test1; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public   class  Main {      public   static   void  main(String[] args) {         ApplicationContext context =  new  ClassPathXmlApplicationContext( "test1/beans.xml" );         SimpleMovieLister m = (SimpleMovieLister)context.getBean( "simpleMovieLister" );         System. out .println(m.getData( "Arthur" ));     } } 控制台上会打印 Hi Arthur! This is JpaMovieFinder implementation! 增加MovieFinder的第二个实现 package test1; import org.springframework.stereotype.Repository; @Repository public   class  IbatisMovieFinder implements MovieFinder {     @Override      public  String getData() {          return   "This is IbatisMovieFinder implementation!" ;     } } 这时运行Main,系统会报错: Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMovieLister': Injection of resource fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [test1.MovieFinder] is defined: expected single matching bean but found 2: [jpaMovieFinder, ibatisMovieFinder] 从错误信息中我们可以看到现在MovieFinder有两个bean实现了,一个是 jpaMovieFinder,另一个是 ibatisMovieFinder,spring容器不知道应该使用哪一个bean。这时可以使用注解 @Qualifier指定具体的bean。 //... @Service public   class  SimpleMovieLister {     @Autowired     @Qualifier( "ibatisMovieFinder" )      private  MovieFinder movieFinder; //... 这里我们指定注入的是 ibatisMovieFinder这个bean。 运行Main, 控制台上会打印 Hi Arthur! This is IbatisMovieFinder implementation!Java6提供的注入注解 spring也可以使用java6提供的@Resource注解来指定注入哪一个bean。 //... @Service public   class  SimpleMovieLister {     @Resource(name= "ibatisMovieFinder" )      private  MovieFinder movieFinder; //... 这和@Autowired功能是一致的。 使用注解还是xml 使用注解很方便,但从上面的例子我们也可以看出注解的问题, MovieFinder有两个实现, SimpleMovieLister是在程序中用注解指定了使用哪一个实现,如果要修改,需要修改源程序。所以,注解只适用于固定依赖的情况。如果依赖需要在部署的时候做调整,那还是使用xml的配置方式方便,毕竟只需要修改一下xml文件即可。 实际使用时,我们可以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-2.5.xsd            http: //www.springframework.org/schema/context            http: //www.springframework.org/schema/context/spring-context-2.5.xsd">                     <context:component-scan  base -package= "test1" />          <bean id= "simpleMovieLister1"   class = "test1.SimpleMovieLister" >         <property name= "movieFinder"   ref = "jpaMovieFinder"  />     </bean>      </beans> 使用xml配置方式定义了另外一bean,注入了 jpaMovieFinder这个实现。 package test1; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public   class  Main {      public   static   void  main(String[] args) {         ApplicationContext context =  new  ClassPathXmlApplicationContext( "test1/beans.xml" );         SimpleMovieLister m = (SimpleMovieLister)context.getBean( "simpleMovieLister" );         System. out .println(m.getData( "Arthur" ));         SimpleMovieLister m1 = (SimpleMovieLister)context.getBean( "simpleMovieLister1" );         System. out .println(m1.getData( "Arthur" ));     } } simpleMovieLister是从注解来的, simpleMovieLister1是从xml配置来的。运行结果: Hi Arthur! This is IbatisMovieFinder implementation! Hi Arthur! This is JpaMovieFinder implementation! 证明混合使用是可行的,你可以继续测试,用xml重新配置 simpleMovieLister。 因此,即使我一开始使用了注解,之后我后悔了,没有关系,不用修改源程序,以前用xml怎么配置现在还是怎么配置。
转载请注明原文地址: https://www.6miu.com/read-5052131.html

最新回复(0)