Spring-IOC(注解版)

上一篇文章讲解了IOCXML版,今天我们来讲解一下注解版。

一、把在Spring的xml文件中配置bean改为Spring的注解来配置bean

传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。

使用注解来构造IoC容器

用注解来向Spring容器注册Bean。
首先在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.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
<!--  开启注解-->
    <context:component-scan base-package="com.it.ioc1;com.it.*"> </context:component-scan>
</beans>

base-package表明com.it.ioc1包及其子包中,如果某个类的头上带有特定的注解【@Component/@Repository/@Service/@Controller】,就会将这个对象作为Bean注册进Spring容器。也可以在<context:component-scan base-package=” ”/>中指定多个包,包与包之间通过;隔开。

准备代码:
IOrderDAO接口

package com.it.ioc1.item.dao;
public interface IOrderDAO {
    void addOrder();
}

IOrderService接口

package com.it.ioc1.item.services;
public interface IOrderService {
    void addOrder();
}

1、@Component
是所有受Spring 管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。
将@Component衍生为三个注解
1.1、@Controller
@Controller对应表现层的Bean
1.2、@ Service
@Service对应的是业务层Bean,例如:

package com.it.ioc1.item.services;
import com.it.ioc1.item.dao.IOrderDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//<bean id="orderServiceImpl" class="com.it.ioc1.item.services.OrderServiceImpl">
//@Component("orderServiceImpl")
@Service("orderServiceImpl")
@Scope
//@Scope("prototype")
public class OrderServiceImpl implements IOrderService {
    IOrderDAO orderDAOImpl;
    private String name;
    public String getName() {
        return name;
    }
    @Override
    public void addOrder() {
        orderDAOImpl.addOrder();
        System.out.println("-----OrderServiceImpl-----------");
    }
}

使用@ Service注解标识OrderServiceImpl之后,就表示要把OrderServiceImpl交给Spring容器管理,在Spring容器中会存在一个名字为"orderServiceImpl"的action,这个名字是根据OrderServiceImpl类名来取的。注意:如果@Service不指定其value【@Service】,则默认的bean名字为这个类的类名首字母小写,如果指定value则使用value作为bean的名字。

这里的OrderServiceImpl还使用了@Scope注解,@Scope(“prototype”)表示将OrderServiceImpl的范围声明为原型,可以利用容器的scope="prototype"来保证每一个请求有一个单独的OrderServiceImpl来处理,避免struts中OrderServiceImpl的线程安全问题。spring 默认scope 是单例模式(scope=“singleton”),这样只会创建一个OrderServiceImpl对象,每次访问都是同一OrderServiceImpl对象,数据不安全,struts2 是要求每次次访问都对应不同的OrderServiceImpl,scope=“prototype” 可以保证当有请求的时候都创建一个OrderServiceImpl对象

1.3、@ Repository
@Repository对应数据访问层Bean
OrderDAOImpl实现IOrderDAO接口,例如:

package com.it.ioc1.item.dao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
//@Component("orderDAOImpl")
@Repository("orderDAOImpl")
public class OrderDAOImpl implements IOrderDAO  {
//      @PostConstruct
    public void init(){
        System.out.println("-----OrderDAOImpl  init-------------");
    }
    @Override
    public void addOrder()
    {
        System.out.println("---OrderDAOImpl add--------------");
    }
    //    @PreDestroy
    public void destroy(){
        System.out.println("-----OrderDAOImpl  destroy---------");
    }
}

@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
(ClassPathXmlApplicationContext) context).close()时触发。

常用注解
1、@Autowired

@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。

@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

package com.it.ioc1.item.services;
import com.it.ioc1.item.dao.IOrderDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//<bean id="orderServiceImpl" class="com.it.ioc1.item.services.OrderServiceImpl">
//@Component("orderServiceImpl")
@Service("orderServiceImpl")
//@Scope
//@Scope("prototype")
public class OrderServiceImpl implements IOrderService {
    @Autowired   //按照类型去匹配
   @Qualifier( value = "orderDAOImpl")
   // @Resource   //按照名称去匹配
    IOrderDAO orderDAOImpl;
    private String name;
    public String getName() {
        return name;
    }
    @Override
    public void addOrder() {
       orderDAOImpl.addOrder();
        System.out.println("-----OrderServiceImpl-----------");
    }
}

这里@Autowired注解的意思就是,当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去。

有一个细节性的问题是,假如bean里面有两个property,Xxx.java里面又去掉了属性的getter/setter并使用@Autowired注解标注这两个属性那会怎么样?答案是Spring会按照xml优先的原则去Xxx.java中寻找这两个属性的getter/setter,导致的结果就是初始化bean报错。 假如bean里面有两个property,Xxx.java里面又去掉了属性的getter/setter并使用@Autowired注解标注这两个属性那会怎么样?答案是Spring会按照xml优先的原则去Xxx.java中寻找这两个属性的getter/setter,导致的结果就是初始化bean报错。
@Autowired(required = false) ,不想让Spring容器抛出异常,而就是显示null

2、Qualifier(指定注入Bean的名称)
如果IOrderService有两个实现类,Spring并不知道应当引用哪个实现类,此时就要使用@Qualifier( value = “orderDAOImpl”)
3、Resource
@Resource注解与@Autowired注解作用非常相似
这是详细一些的用法,说一下@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之间的耦合。

测试类

package com.it.ioc1.item.testIOC;
import com.it.ioc1.item.services.IOrderService;
import com.it.ioc1.item.services.OrderServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringIOCTest {
    @Test
    public void addOrder(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        IOrderService  service = context.getBean("orderServiceImpl", OrderServiceImpl.class);
         service.addOrder();
        System.out.println(((OrderServiceImpl) service).getName());
//         ((ClassPathXmlApplicationContext) context).close();
	}
}

Spring还提供了自己的@Test单元测试
导包:
spring-test-4.2.4.RELEASE.jar

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:applicationContext.xml")
 @Test
public class SpringAOPTest1 {
		@Resource
		IOrderService  service;
		 service.addOrder();
        System.out.println(((OrderServiceImpl) service).getName());
}

二、小结
本文汇总了Spring的常用注解,以方便大家查询和使用,具体如下:
使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包)。

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Lazy(true) 表示延迟初始化

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

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

@Service用于标注业务层组件、

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

@Scope用于指定scope作用域的(用在类上)

@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合**@Qualifier**注解一起使用。如下:
@Autowired @Qualifier(“personDaoBean”) 存在多个实例配合使用

@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
@DependsOn:定义Bean初始化及销毁时的顺序
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Async异步方法调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值