今天将写的是有关基于注解方式配置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();
}
}