Spring 通过IOC实现对象的管理,而IOC的具体实现,依赖于DI依赖注入对对象的属性进行赋值。
DI 通过配置文件或注解的方式指定对象与对象之间的依赖关系,并依据该依赖关系对对象属性进行赋值。
DI依赖注入的方式:
1) set方法注入:类中的属性必须实现set方法。在bean标签中配置<property> 标签,指定set注入的依赖关系(在xml配置中使用最多);
private BbyeService byeService;
public void setByeService(BbyeService byeService){
this.byeService=byeService;
}
<bean id="eByeService" class="spring.EByeService"></bean> <bean id="zByeService" class="spring.ZByeService"></bean> <bean id="userAction" class="spring.UserAction"> <!-- set注入,类中的属性必须实现set方法,--> <!-- spring会通过反射调用对象的set方法完成属性的赋值–>--> <!-- property:配置类的属性; ref:关联到具体的bean–>--> <property name="helloService" ref="zhHelloService"></property> <property name="byeService" ref="zByeService"></property> </bean>
2) 构造器注入:类中定义带属性参数的构造方法,在bean中配置<constructor-arg> 配置构造器;
<!--开启注解,配置扫描包,spring会在对应的包下去扫描配置了注解的类-->
<context:component-scan base-package="before,spring,aop"></context:component-scan>
<bean id="userAction" class="spring.UserAction">
<!-- 构造器注入,index指定下标 从0开始,type 指定类型-->
<constructor-arg index="0" ref="zhHelloService"></constructor-arg>
<constructor-arg index="1" ref="eByeService"></constructor-arg>
</bean>
public UserAction() { } //构造器注入,需要创建有参构造方法 public UserAction(HelloService helloService) { this.helloService = helloService; }
3) 注解注入:在spring配置文件中指定开启注解,并在对应的类上添加注解。常用注解有:
a.扫描bean的注解。相当于在xml中定义<bean>标签
a)@Controller:用于控制层的注解。(整合Struts2/springmvc时,用来标注控制层类)
@Controller("a") //<bean class="spring.UserAction">
b)@Service: 用于Service业务逻辑处理层的注解
@Service("zByeService") public class ZByeService implements BbyeService { @Override public void sayBye() { System.out.println("你好呀"); } }
c)@Repository: 用于Dao层注解
d)@Component :用于其他组件
===============================重点,面试经常问的===================================
b.依赖注入的注解:写在属性上,或对应set方法上
a)@Autowired:spring的注解,按照类型进行注入。
//required:指定对象是否必须,为false,则可以为null(即使查找的对象不存在,也不会报错,只会报空指针异常),默认为true(如果找不到对象,就会报错,报找不到对象的错误) @Autowired(required = true) private HelloService helloService;
b)@Resource:java提供的注解,默认根据名称注入(指定了name,则根据name,没指 定name,则根据属性名),没有对应名称则按照类型注入。
//Resource(name):指定注入对象的名称(id),当一个接口有多个实现类的情况下 //如果没有通过name指定注入的对象名,则会先根据属性名称进行注入,如果不存在对应的对象,则根据类型进行注入 @Resource(name = "eByeService") //指定name,就按name来;不指定name,就按byeService(属性的名称)来,再找不到,就按BbyeService(类型)来; private BbyeService byeService;
c)@Qualifier:配合@Autowired使用,指定注入对象的名称===>这两个配合使用起来就相当于@Resource;
@Qualifier("zhHelloService") //required:指定对象是否必须,为false,则可以为null(即使查找的对象不存在,也不会报错,只会报空指针异常),默认为true(如果找不到对象,就会报错,报找不到对象的错误) @Autowired(required = true) private HelloService helloService;
=======================================================================================
c.其他注解
a)@Scope 指定对象的作用域(创建方式和生命周期)
i.单例(默认的)singletion
public static void main(String[] args) { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/applicationContext2.xml"); UserAction userAction1= (UserAction) applicationContext.getBean("a"); UserAction userAction2= (UserAction) applicationContext.getBean("a"); System.out.println(userAction1==userAction2);//true 说明是同一个对象,默认创建方式是单例 }
因为是单例模式,所有对象只创建一次,所有值也就相等;
ii.Prototype:多实例(struts2)
@Scope("prototype")//指定为多实例
因为是多例模式,所以对象创建两次,值也就不相等了;
iii.Request: bean的生命周期与request请求一致(springmvc)
iv.Session:bean的生命周期与session一致(springmvc)
v.Global Session: application
b)@PostConstruct: 初始化方法 ==>init-method
c)@PreDestory:销毁方法 ==>destory-method
d)@Lazy: 懒加载注解,指定spring容器加载时不去创建该对象
@Lazy//延迟加载