赞
踩
上一篇文章讲解了IOCXML版,今天我们来讲解一下注解版。
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
用注解来向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异步方法调用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。