Spring IOC容器装配bean----------------注解方式

Spring Bean配置的三种不同方式,主要包括:

  • 基于XML的配置方式
  • 基于注解的配置方式
  • 基于Java类的配置方式

在本文中我将结合自己实际情况来介绍第二种基于注解的配置方式

使用注解方式,主要是为了替代xml文件,使开发更加快速。但是,xml文件的使用就是解决修改程序修改源代码,现在又不去使用xml文件,那么不就违背了开闭原则了么,的确是。不过么,注解也有注解的好,使用注解就不用配置那么多的xml文件啦,最重要的是开发效率高。。

  在没有使用注解时,spring框架的配置文件applicationContext.xml文件中需要配置很多的<bean>标签,用来声明类对象。使用注解,则不必在配置文件中添加标签拉,对应的是在对应类的“注释”位置添加说明

首先我在一个web项目集成spring,来介绍这种方法在web中的一些配置

[开发工具]

IDEA,Tomcat

[相应的架包]

这些基本的架包到官网下载或者到这个网站下载http://how2j.cn/

[项目相应的包]

首先是在web下新建一个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.wyf" ></context:component-scan>

</beans>
<context:component-scan base-package="com.wyf" ></context:component-scan>

这段代码的意思是通过注解扫描来告诉框架那些类是使用注解的,也就是com.wyf下面的包中的所有类

[注解有哪些]

spring框架使用的是分层的注解。

    持久层:@Repository;

    服务层:@Service

    控制层:@Controller

首先是持久层注解@Repository对应数据访问层Bean

package com.wyf.dao;

import org.springframework.stereotype.Repository;


@Repository
public class UserDao {

    public void save(){
        System.out.print("通过注解扫描成功完成测试");
    }
}

这里的@Repository 等同于配置文件中的

<bean id="userDao" class="com.wyf.UserDao" />  

服务层注解@Service对应的是业务层Bean

package com.wyf.service;

import com.wyf.dao.UserDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


@Service(value = "userDao")
public class UserService {
    @Resource//相当于自动装配 
    private UserDao userDao;

    public void addUser(){
        userDao.save();
    }
}

@Resource 对象间关系的组合,默认采用的是byName方式进行装配,如果根据名称查找不到关联的对象,那么会再采用byType继续查找。

@Service注解等同与<bean id="userService" class="com.wyf.UserService" />

控制层注解@Controller对应表现层的Bean,也就是Action

package com.wyf.action;

import com.wyf.service.UserService;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;


@Controller(value = "userService")
public class UserAction {
    @Resource
    private UserService userService;
    public void addUser(){
        userService.addUser();
    }
}

@Controller注解等同于<bean id="userService" class="com.wyf.UserAction " /> 

[补充下]

在Action声明的“userService”变量的类型必须是“UserServiceImpl”或者是其父类“UserService”,否则由于类型不一致而无法注入,由于Action中的声明的“userService”变量使用了@Resource注解去标注,并且指明了其name = "userService",这就等于告诉Spring,说我Action要实例化一个“userService”,你Spring快点帮我实例化好,然后给我,当Spring看到userService变量上的@Resource的注解时,根据其指明的name属性可以知道,Action中需要用到一个UserServiceImpl的实例,此时Spring就会把自己创建好的名字叫做"userService"的UserServiceImpl的实例注入给Action中的“userService”变量,帮助Action完成userService的实例化,这样在Action中就不用通过“UserService userService = new UserServiceImpl();”这种最原始的方式去实例化userService了。如果没有Spring,那么当Action需要使用UserServiceImpl时,必须通过“UserService userService = new UserServiceImpl();”主动去创建实例对象,但使用了Spring之后,Action要使用UserServiceImpl时,就不用主动去创建UserServiceImpl的实例了,创建UserServiceImpl实例已经交给Spring来做了,Spring把创建好的UserServiceImpl实例给Action,Action拿到就可以直接用了。Action由原来的主动创建UserServiceImpl实例后就可以马上使用,变成了被动等待由Spring创建好UserServiceImpl实例之后再注入给Action,Action才能够使用。这说明Action对“UserServiceImpl”类的“控制权”已经被“反转”了,原来主动权在自己手上,自己要使用“UserServiceImpl”类的实例,自己主动去new一个出来马上就可以使用了,但现在自己不能主动去new“UserServiceImpl”类的实例,new“UserServiceImpl”类的实例的权力已经被Spring拿走了,只有Spring才能够new“UserServiceImpl”类的实例,而Action只能等Spring创建好“UserServiceImpl”类的实例后,再“恳求”Spring把创建好的“UserServiceImpl”类的实例给他,这样他才能够使用“UserServiceImpl”,这就是Spring核心思想“控制反转”,也叫“依赖注入”,“依赖注入”也很好理解,Action需要使用UserServiceImpl干活,那么就是对UserServiceImpl产生了依赖,Spring把Acion需要依赖的UserServiceImpl注入(也就是“给”)给Action,这就是所谓的“依赖注入”。对Action而言,Action依赖什么东西,就请求Spring注入给他,对Spring而言,Action需要什么,Spring就主动注入给他。

使用注解声明对象,默认情况下生成的id名称为类名称的首字母小写。

上面的基本配置说完了,接下来就是要说一下web项目中web.xml中配置Spring IOC 容器加载

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--配置Spring IOC 容器的加载-->
    <!-- Spring监听器  -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/WEB-INF/bean.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 在实际项目中spring的配置文件applicationcontext.xml是通过spring提供的加载机制自动加载到容器中。在web项目中,配置文件加载到web容器中进行解析。目前,spring提供了两种加载器,以供web容器的加载:一种是ContextLoaderListener,另一种是ContextLoaderServlet。这两种在功能上完全相同,只是前一种是基于Servlet2.3版本中新引入的Listener接口实现,而后一种是基于Servlet接口实现,以下是这两种加载器在web.xml中的配置应用:

ContextLoaderListener

<listener>
<listener-class>org.springframework.context.ContextLoaderListener</listener-class>
</listener>

ContextLoaderServlet

<servlet>
 <servlet-name>context</servlet-name>
<servlet-class>org.springframework.context.ContextLoaderServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>

通过上面的配置,web容器会自动加载applicationcontext.xml初始化。

如果需要指定配置文件的位置,可通过context-param加以指定:

  <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/WEB-INF/bean.xml</param-value>
    </context-param>
<param-value>classpath*:/WEB-INF/bean.xml</param-value>

这段代码是我存放bean.xml的目录前面那个classpath*如果没有后面那个*号就会出现

java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

反正我当时是这样出错的你们可以借鉴下

如果上面的配置基本完成那么我们运行下index.jsp成功那么说明我们配置ok了

我自己运行成功了

 

猜你喜欢

转载自blog.csdn.net/wyf2017/article/details/81193634