Spring注解@Component、@Repository、@Service、@Controller区别

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。
在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。

@Service用于标注业务层组件

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Service 
public class VentorServiceImpl implements iVentorService {    
} 
@Repository 
public class VentorDaoImpl implements iVentorDao {  
} 

在一个稍大的项目中,如果组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找以及维护起来也不太方便。 
Spring2.5为我们引入了组件自动扫描机制,他在类路径下寻找标注了上述注解的类,并把这些类纳入进spring容器中管理。
它的作用和在xml文件中使用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:annotation-config /> 
    <context:component-scan base-package=”com.eric.spring”>    
</beans>  

1.annotation-config是对标记了 Spring's @Required、@Autowired、JSR250's @PostConstruct、@PreDestroy、@Resource、JAX-WS's @WebServiceRef、EJB3's @EJB、JPA's @PersistenceContext、@PersistenceUnit等注解的类进行对应的操作使注解生效。
2.base-package为需要扫描的包(含所有子包),负责扫描那些类有注解。

 

getBean的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”)这样来指定。
这种bean默认是“singleton”的,如果想改变,可以使用@Scope(“prototype”)来改变。

可以使用以下方式指定初始化方法和销毁方法:

@PostConstruct 
public void init() {  
}  
@PreDestroy 
public void destory() {  
} 

注入方式:

@Autowired

@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property

注入时不要new 这个注入的类,因为spring会自动注入,如果手动再new的话会出现错误,然后属性加上@Autowired后不需要getter()和setter()方法

当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。

@Autowired接口注入

上面的比较简单,我们只是简单注入一个Java类,那么如果有一个接口,有多个实现,Bean里引用的是接口名,又该怎么做呢?比如有一个Car接口:

public interface Car
{
    public String carName();
}

两个实现类BMW和Benz:

@Service
public class BMW implements Car
{
    public String carName()
    {
        return "BMW car";
    }
}
@Service
public class Benz implements Car
{
    public String carName()
    {
        return "Benz car";
    }
}

写一个CarFactory,引用Car:

@Service
public class CarFactory
{
    @Autowired
    private Car car;
    public String toString()
    {
        return car.carName();
    }
}

不用说,一定是报错的,Car接口有两个实现类,Spring并不知道应当引用哪个实现类。这种情况通常有两个解决办法:

1、删除其中一个实现类,Spring会自动去base-package下寻找Car接口的实现类,发现Car接口只有一个实现类,便会直接引用这个实现类

2、实现类就是有多个该怎么办?此时可以使用@Qualifier注解:当接口存在两个实现类的时候必须使用@Qualifier指定注入哪个实现类

@Service
public class CarFactory
{
    @Autowired
    @Qualifier("BMW")
    private Car car;
    public String toString()
    {
        return car.carName();
    }
}

注意@Qualifier注解括号里面的应当是Car接口实现类的类名,我之前试的时候一直以为是bean的名字,所以写了"bMW",结果一直报错。

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解

1、共同点

两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

@Resource

@Service
public class Zoo
{
    @Resource(name = "tiger")
    private Tiger tiger;

    @Resource(type = Monkey.class)
    private Monkey monkey;

    public String toString()
    {
        return tiger + "\n" + monkey;
    }
}

这是详细一些的用法,说一下@Resource的装配顺序:

1、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配

2、指定了name或者type则根据指定的类型去匹配bean

3、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错

 

然后,区分一下@Autowired和@Resource两个注解的区别:

1、@Autowired默认按照byType方式进行bean匹配,

      @Resource默认按照byName方式进行bean匹配

2、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了

Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

 

<!-- 定义跳转的文件的前后缀 ,视图模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
 <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
	<!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->
	<property name="prefix" value="/WEB-INF/views/" />
	<property name="suffix" value=".jsp" />
</bean>

 

@Controller
@RequestMapping ( "/test" )
public class MyController {
   
 1. 返回ModelAndView
    //@RequestMapping ( "/showView" )
    @RequestMapping(value = "/showView", method = RequestMethod.GET)
    public ModelAndView showView() {
       ModelAndView modelAndView = new ModelAndView();
       modelAndView.setViewName("viewName"); // 跳转的页面  
       modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " );
       // modelAndView.addObject("users", users);  
       return modelAndView;
    }

    //当访问localhost:8080/hello?username=ted时,值ted会绑定到参数username上,结果是 Hello ted 
    @RequestMapping(value=/hello)
    String sayHelloToUser(@RequestParam("username") String username){
        return "Hello " + username;
     // return "items/edititems";
    }

3. 返回字符串
  // @RequestMapping 来处理多个 URI 
  @RequestMapping(value={"", "/page", "page*","view/*"})
    String multipleMapping(){
        return "Hello";
    }
  • localhost:8080/home
  • localhost:8080/home/
  • localhost:8080/home/page
  • localhost:8080/home/pageabc
  • localhost:8080/home/view/
  • localhost:8080/home/view/vi
@RequestMapping("/list")
public String userList(Model model){
    User user = new User();
    model.addAttribute("user", User);
    return "operator/list";
}

页面上${user}获得对象,${user.userName}获得用户名(对象点属性)
也可以返回Model,方式多种多样,这样子写你可能更容易理解一些。
如果是ajax异步调用的话,需要加上@ResponseBody标签,在返回的时候随便返回对象,集合,字符串等的都可以的。

只想返回数据而不返回页面时

    //@RequestMapping("c")
    @RequestMapping(value=/c)
    @ResponseBody
    public String d()
    {
        HashMap s = new HashMap();
        s.put("aaa", "你好啊");
        return s;
    }

è¿éåå¾çæè¿°

@RestController的意思就是controller里面的方法都以json格式输出,

@RestController
public class HelloWorldController {
    @RequestMapping("/hello")
    public String index() {
        return "Hello World";
    }
}

在方法上添加

使用@RestController注解等于使用@Controller和@ResponseBody两个注解。返回对象

标注@ResponseBody就是输出json

@RestController
public class LoginController { 
          ......
 @RequestMapping("/login")
   public User login(User user){
          ......
    return user; }

@Controller
@ResponseBody
public class LoginController {  
        ......
 @RequestMapping("/login")
   public User login(User user){
          ......
    return user; }
那么在前台接收到的数据为:'{"userName":"xxx","pwd":"xxx"}'

或者在方法上
    @RequestMapping("/login")
  @ResponseBody
  public User login(User user){
          ......
    return user;
  }


效果等同于如下代码:
  @RequestMapping("/login")
  public void login(User user, HttpServletResponse response){
          ......
    response.getWriter.write(JSONObject.fromObject(user).toString());
  }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值