SpringFramework学习-(10)注解分析

上一篇SpringFramework学习-(9)基于注解配置bean
介绍了如何从配置文件配置bean到通过注解配置bean的转移,中间用到了几个常用的注解。Spring提供了很多的注解,没法一一的都介绍。本篇将介绍一下常用的各个注解都是什么意思,该在哪里使用这个注解。

1.@Component

@Controller@Serivce@Repository@Component四个注解通常被用来标记类。如果某个类的头上带有这些特定的注解,通过<context:component-scan base-package=” ”/> 扫描就可以将这些类注册到SpringIoC容器之中。

@Component是所有受Spring 管理组件的通用形式,仅仅表示一个组件 (Bean) ,可以作用在任何层次,@Component注解可以放在类的头上,但是实际的运用中@Component不推荐使用。

有了这个通用组件@Component,为了区分不同层面上的组件,Spring提供了其他@Controller@Serivce@Repository 分别用于标识控制层,业务层,数据层的bean。

很多人包括笔者之前也纠结于这几个注解到底有什么区别呢?

这里写图片描述

这里写图片描述

带着疑问,打开这几个注解的源码可以看到内部实际并没有任何的区别,都只有简单的一行代码。同时我们也看到了这些注解也都是通过@Component组件进行标记的。

String value() default "";

但是我们还是没有找到他们之间的区别是什么 ,于是我们来到Spring的官方文档,看看官方文档是怎么说的:
|————————————————————————————————————————–
The @Repository annotation is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO). Among the uses of this marker is the automatic translation of exceptions as described in Section 19.2.2, “Exception translation”.

Spring provides further stereotype annotations: @Component, @Service, and @Controller. @Component is a generic stereotype for any Spring-managed component. @Repository, @Service, and @Controller are specializations of @Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively. Therefore, you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. It is also possible that @Repository, @Service, and @Controller may carry additional semantics in future releases of the Spring Framework. Thus, if you are choosing between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated above, @Repository is already supported as a marker for automatic exception translation in your persistence layer.

@Component组件是任何spring管理组件的通用原型。 @Repository@Service@Controller是针对更具体的用例(例如,在持久性、服务和表示层)中的@component的专门化。因此,您可以使用@Component来注释您的组件类,但是通过使用@Repository@Service@Controller来注解它们,您的类更适合于使用工具进行处理或与面向切面Aspects关联,例如,这些原型注解为切入点提供了理想的目标。在Spring框架的未来版本中,@Repository@Service@Controller也可能带有附加的语义。因此,如果您选择使用@Component@Service为您的服务层,@Service显然是更好的选择。类似地,如上所述,在您的持久层中,@Repository已经作为自动异常转换的标记支持。
—————————————————————————————————————————|
官方文档说的再清楚不过了。这几个主机本质上并没有区别,只是做为各层级的标记。方便面向切面指定切入点,在未来的Spring版本升级中可能会给各个注解添加语义,同时对异常处理做了一些标记支持。

所以到此我们就不用再纠结于他们之间的区别了。

通过xml配置文件,我们可以配置bean的作用域,加载方式等属性,通过注解也可以配置:
@Scope(“prototype”),@Scope(“singleton”)
@Lazy(true),@Lazy(false)

2.@Configuration和@Bean

这个一直是比较不好理解的东西,官方文档给出的例子是

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }

}

等同于

<beans>
    <bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>

怎么理解呢,实际上就是把@Configuration标注的类看做是一个IOC容器,而把类里面@Bean标注的方法看作是IOC容器里面的bean。
还是不能够理解是吧,那么我们写个小例子运行一下看看:

有一个Person类

package com.jd.annotation2;
public class Person {
    private int id;
    private String userName;
    private String loginName;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getLoginName() {
        return loginName;
    }
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public Person() {
        System.out.println("Person constructor...");
    }
}

有一个UserService和UserServiceImpl实现

package com.jd.annotation2.service;

public interface UserService {

    public void addInt(int a,int b);
}
package com.jd.annotation2.service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.jd.annotation2.dao.UserDao;

@Service("userService")
@Scope("prototype")
@Lazy(true)
public class UserServiceImpl implements UserService{

    public void addInt(int a ,int b) {
        System.out.println("userService ... addInt");
    }

}

有一个类提供了两个方法,分别提供Person和UserServiceImpl

package com.jd.annotation2;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.jd.annotation2.service.UserService;
import com.jd.annotation2.service.UserServiceImpl;

@Configuration
public class AppCig {

    @Bean
    public Person getPerson(){
        return new Person();
    }

    @Bean
    public UserService getUserService(){
        return new UserServiceImpl();
    }
}

测试一下:

package com.jd.annotation2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jd.annotation2.service.UserService;

public class AnnotationTest2 {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("springannotation2.xml");
        Person p = (Person)ac.getBean("getPerson");
        System.out.println(p);

        UserService us = (UserService)ac.getBean("getUserService");
        System.out.println(us);
    }
}

结果:

Person constructor…
com.jd.annotation2.Person@65466a6a
com.jd.annotation2.service.UserServiceImpl@4ddced80

我们发现我们可以直接在IOC容器之中直接调用getPerson()和getUserService()方法。@Bean注释用于指示方法实例化、配置和初始化一个新的对象,由Spring IoC容器管理。对于熟悉Spring的<bean/> XML配置的人来说,@Bean注释与<bean/>元素具有相同的作用。当然也可以使用@Bean@Component 配合使用,但是大多数情况下还是使用@Bean@Configuration 组合使用。

3.@PostConstruct和@PreDestroy

前面在Bean的特性中介绍到Bean的声明周期。通过注解也可以完成Bean声明周期的管理。
@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
看例子:
userDaoImpl添加两个方法postConstruct1()和preDestroy1()

@Repository("userDao")
public class UserDaoImpl implements UserDao{

    public void add(int a, int b) {
        int result = a+b;
        System.out.println("调用加法操作,result:"+result);

    }

    public void pur(int a, int b) {
        int result = a-b;
        System.out.println("调用减法操作,result:"+result);
    }


     @PostConstruct
      public void postConstruct1(){
          System.out.println("userDao ... postConstruct1");
      }

      @PreDestroy
      public void preDestroy1(){
          System.out.println("userDao ... preDestroy1"); 
      }
}

userServiceImpl添加两个方法postConstruct1()和preDestroy1()

package com.jd.annotation2.service;


import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.jd.annotation2.dao.UserDao;

@Service("userService")
@Scope("prototype")
@Lazy(true)
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDao userDao;

    public void addInt(int a ,int b) {
        userDao.add(a, b);
    }

      @PostConstruct
      public void postConstruct1(){
          System.out.println("userService ... postConstruct1");
      }

      @PreDestroy
      public void preDestroy1(){
          System.out.println("userService ... preDestroy1"); 
      }

}

测试:

public class AnnotationTest {

    private ClassPathXmlApplicationContext ac = null;
    private UserService userService = null;

    {
        ac = new ClassPathXmlApplicationContext("springannotation2.xml");
        userService = ac.getBean(UserService.class);
    }

    @Test
    public void testAnnotation(){
        userService.addInt(1, 2);
        ac.close();
    }
}

结果:

userDao … postConstruct1
userService … postConstruct1
调用加法操作,result:3
[org.springframework.context.support.ClassPathXmlApplicationContext]Closing org.springframework.context.support.ClassPathXmlApplicationContext@31b7dea0: startup date [Fri Dec 29 14:27:09 CST 2017]; root of context hierarchy
userDao … preDestroy1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值