今天将写的是有关基于注解方式配置bean,因此需要认识一个东西——组件扫描。什么是组件扫描,Spring 能够从 classpath 下自动扫描,侦测和实例化具有特定注解的组件。而它的特定组件包括@Component(基本注解, 标识了一个受 Spring 管理的组件)、@Respository(标识持久层组件)、@Service(标识服务层(业务层)组件)、@Controller(标识表现层组件)。其实就这样看总会有点云里雾里的感觉,所以就一下面的代码为例子,大家就会懂了。
接下来会创建工程目录基本是这样的,接下来会一个一个文件讲。
1)Test.java 主要是@compent
package com.spring; import org.springframework.stereotype.Component; @Component public class Test { }2)创建控制层 UserController.java 主要是@Controller
package com.spring.controller; import org.springframework.stereotype.Controller; @Controller public class UserController { public void execute() { System.out.println("UserController。。。。"); } }3)创建一个持久层UserReporitory.java(接口)、UserReporitoryImpl
package com.spring.Resporitory; public interface UserReporitory { public void save(); } package com.spring.Resporitory; import org.springframework.stereotype.Repository; @Repository public class UserReporitoryImpl implements UserReporitory{ @Override public void save() { // TODO Auto-generated method stub System.out.println("add()......."); } }4)创建一个服务层 UserService.java,这里重点是@Service
package com.spring.Service; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import org.springframework.stereotype.Service; @Service("userService") public class UserService { public void add() { System.out.println("add....."); } }5)当然这些都设置好了,但是光是这样设置Spring是无法识别到的,所以还需要在Spring 的配置文件中声明 <context:component-scan> ,才能识别到你的文件。创建application.xml。
1、base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.。
2、当需要扫描多个包时, 可以使用逗号分隔。
<?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:aop="http://www.springframework.org/schema/aop" 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-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <context:component-scan base-package="com.spring"></context:component-scan> </beans>6)创建Main.java并准备运行,这里的ctx.getBean(..),如果你没有向上面的(4)@Service(userService)注明是这个名字,Spring一般默认是这个类的名字一定字的小写。所以你想全部注明好名字都是可以的,无非是识别的作用。
package com.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.spring.Resporitory.UserReporitory; import com.spring.Service.UserService; import com.spring.controller.UserController; public class Main { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("application.xml"); Test test=(Test) ctx.getBean("test"); System.out.println(test); UserController userController=(UserController) ctx.getBean("userController"); System.out.println(userController); UserReporitory userReporitory=(UserReporitory) ctx.getBean("userReporitoryImpl"); System.out.println(userReporitory); UserService userService=(UserService) ctx.getBean("userService"); System.out.println(userService); } }结果:
com.spring.Test@61ca2dfa com.spring.controller.UserController@4b53f538 com.spring.Resporitory.UserReporitoryImpl@134593bf com.spring.Service.UserService@4bb4de6a
这跟使用基于 XML 文件的方式配置bean的的方向还是很相似的,如果你只想扫描某个包,举个例子:上面在application.xml中<context:component-scan base-package="com.spring"></context:component-scan>是扫描了com.spring下的包以及相关的子包。如果你只想扫描com.spring.service包。那么application.xml需要怎么改 <context:component-scan base-package="com.spring" resource-pattern="Service/*.class" ></context:component-scan>在原先的基础上添加resource-pattern属性过滤特定的类。
那么就会想bean与bean之间的又该怎么相连呢?比如说在UserController.java文件里这样.....修改,添加userService。运行程序会发现报空指针的错误。这是因为userController并没有装配userService,所以无法识别userService就出现空指针了。
package com.spring.controller; import org.springframework.stereotype.Controller; import com.spring.Service.UserService; @Controller public class UserController { private UserService userService; public void execute() { System.out.println("UserController。。。。"); userService.add(); } }因此为了解决这个问题你就需要添加@Autowired (@Autowired 注解自动装配具有兼容类型的单个 Bean属性),使用@Autowired后Spring会寻找有没有跟UserService这个类兼容的bean。
package com.spring.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import com.spring.Service.UserService; @Controller public class UserController { @Autowired private UserService userService; public void execute() { System.out.println("UserController。。。。"); userService.add(); } }如果存在两个跟UserService类似的bean,这时又该怎么办呢。有一个最简单方法添加@Qualifier("userService"),使用@Qualifier识别你要自动装配的bean,这样你就需要注明bean的名字了就像@Service(“userService”)。
package com.spring.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import com.spring.Service.UserService; @Controller public class UserController { @Autowired @Qualifier("userService") private UserService userService; public void execute() { System.out.println("UserController。。。。"); userService.add(); } }还有一种方法如下所示啦,首先@AutoWired是可以放在方法上的,之后@AutoWired会根据setUserService()中UserService这个名进行装配,这样就有唯一性了。
package com.spring.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import com.spring.Service.UserService; @Controller public class UserController { private UserService userService; @Autowired public void setUserService(UserService userService) { this.userService = userService; } public void execute() { System.out.println("UserController。。。。"); userService.add(); } }当然还可以把@Qualifier("userService")放在方法的参数里,运行程序时没什么问题的。
package com.spring.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import com.spring.Service.UserService; @Controller public class UserController { private UserService userService; @Autowired public void setUserService(@Qualifier("userService")UserService userService) { this.userService = userService; } public void execute() { System.out.println("UserController。。。。"); userService.add(); } }