Spring_IOC 之 bean 的配置

来源:互联网 发布:产品经理和程序员待遇 编辑:程序博客网 时间:2024/06/08 09:40
1.Spring之Bean创建三种方式:
(1) 调用构造器创建Bean
     调用构造方法创建Bean是最常用的一种情况Spring容器通过new关键字调用构造器来创建Bean实例,通过class属性指定Bean实例的实现类,也就是说,如果使用构造器创建Bean方法,则<bean/>元素必须指定class属性,其实Spring容器也就是相当于通过实现类new了一个Bean实例。调用构造方法创建Bean实例,通过名字也可以看出,我们需要为该Bean类提供无参数的构造器。下面是一个通过构造方法创建Bean的最简单实例。
     ① Bean实例实现类 Person.java
package com.atguigu.spring.pojo;public class Person {      private String name;         public Person()   {             System.out.println("Spring容器开始通过无参构造器创建Bean实例------------");         }         public void setName(String name){             this.name = name;         }         public void input(){             System.out.println("欢迎来到我的博客:"+name);         }}
     因为是通过构造函数创建Bean,因此我们需要提供无参数构造函数,另外我们定义了一个name属性,并提供了setter方法,Spring容器通过该方法为name属性注入参数。
     ② 配置文件beans.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"     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- 指定class属性,通过构造方法创建Bean实例 -->    <bean id="person" class="com.atguigu.spring.pojo.Person">      <!-- 通过调用setName方法,将VipMao作为参数传入 -->      <property name="name" value="Luo"></property>    </bean></beans>
     配置文件中,通过<bean>元素的id属性指定该bean的唯一名称,class属性指定该bean的实现类,可以理解成Spring容器就是通过该实现类new了一个Bean。通过<property>标签的name属性和value属性指定了:调用setName方法,将VipMao作为参数注入。
     ③ 测试类 PersonTest.java
package com.atguigu.spring.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.atguigu.spring.pojo.Person;public class PersonTest {     public static void main(String[]args){         //创建Spring容器         ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");         //通过getBean()方法获取Bean实例         Person person=(Person)ctx.getBean("person");         person.input();       } }
     ④运行结果

     通过静态工厂创建Bean,是不是听着高大上了?顾名思义,咱们把创建Bean的任务交给了静态工厂,而不是构造函数,这个静态工厂就是一个Java类,那么使用静态工厂创建Bean咱们又需要添加哪些属性呢?我们同样需要<bean/>元素内添加class属性,上面也说了,静态工厂是一个Java类,那么该class属性指定的就是该工厂的实现类,而不再是Bean的实现类,告诉Spring这个Bean应该由哪个静态工厂创建,另外我们还需要添加factory-method属性来指定由工厂的哪个方法来创建Bean实例,因此使用静态工厂方法创建Bean实例需要为<bean/>元素指定如下属性:(2) 调用静态工厂方法创建Bean
class:指定静态工厂的实现类,告诉Spring该Bean实例应该由哪个静态工厂创建(指定工厂地址)
factory-method:指定由静态工厂的哪个方法创建该Bean实例(指定由工厂的哪个车间创建Bean) ,如果静态工厂方法需要参数,则使用<constructor-arg.../>元素传入 。
(3) 调用实例工厂方法创建Bean
      其实调用实例工厂创建Bean和调用静态工厂创建Bean的区别就在于,调用实例工厂将工厂单独拿了出来(先实例化工厂)创建一个工厂Bean,通过工厂<bean>的class属性指定工厂的实现类,然后再需要创建其他Bean时,只需要在该<bean/>元素添加factory-bean、factory-method指定该Bean是有哪个实例工厂的哪个方法创建就可以了,放在现实生活中就是:我们先找一个地方创建一个工厂,id指定工厂注册名字(xxx有限公司),class指定公司所在地,工厂里面有车间(创造其他Bean的方法),那好有了工厂我们再需要创建其他Bean时,只需要指定这个Bean是由,哪个工厂的哪个车间创建的即可,也就是只需要在该<bean/>元素添加factory-bean、factory-method属性即可。

2.Spring容器对Bean组件的管理
          scope="singleton"    单例的。默认值
          scope="prototype"   多例的。
          scope= "session": 一次会话。
          scope= "request": 一次请求。

3.获取Bean的方式
      根据id获取Bean对象:
          Student student = (Student)ioc.getBean("student");
      根据类型获取Bean对象:根据类型查找Bean,必须保证只能查找到一个Bean对象,如果有多个会报错。
          Student student = ioc.getBean(Student.class);

4.bean的生命周期:
     ① 定义
     ② 初始化
     ③ 使用
     ④ 销毁
     说明:默认配置全局的初始化,销毁方法,如果不设置,系统会自动加上。
5.Spring_IOC之XML自动装配:
(1) 在beans.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"     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">     <!--           autowire : 自动装配                byName : 表示根据属性名称(不是成员变量名称)来查找关联的Bean对象,然后,注入到当前Bean对象中,进行属性赋值                byType : 表示根据属性类型来查找关联的Bean对象,如果存在,就注入到当前Bean对象中,进行属性赋值                     如果查找到多个相同类型的对象,属性为单数类型,注入失败;可以采用复数类型(数组或集合(泛型))接收多个对象;      -->     <bean id="userService2" class="com.pers.spring.component.UserServiceImpl" autowire="byType">           <!-- <property name="userDao" ref="userDao2"></property> -->     </bean> <!--      <bean id="userDao2" class="com.pers.spring.component.UserDaoImpl"></bean>           <bean id="userDao3" class="com.pers.spring.component.UserDaoImpl"></bean> --></beans>
(2) 在UserServiceImpl中:
package com.pers.spring.component;import java.util.List;public class UserServiceImpl implements UserService{     private List<UserDaoImpl> userDao ;     private String message ;     public void setUserDao(List<UserDaoImpl> userDao) {           this.userDao = userDao;     }     public void saveUser(){           userDao.get(0).save();     }     public String getMessage() {           return message;     }     public void setMessage(String message) {           this.message = message;     }     public List<UserDaoImpl> getUserDao() {           return userDao;     }}
(3) 在测试类中
package junit.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.pers.spring.component.UserService;public class TestIOC_Autowire {     ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");     @Test     public void testAutowire() {           UserService userService = (UserService)ioc.getBean("userService2");           System.out.println(userService);     }}
6.Spring_IOC的Annotation完成自动装配:
(1) XML和Annotation两种开发方式
① XML :
<bean id="student" class="com.atguigu.spring.bean.Student" scope="prototype"></bean>
② Annotation :
@Component
@Scope("prototype") //多例创建对象
public class Student(){}
(2) Spring框架提供了分层注解,来声明各个层中的Bean对象
@Controller   用于表现层
@Service   用于服务层
@Repository   用于持久化层
@Component  用于哪些不太明确属于某个层的Bean对象的声明,比较通用,可以代替分层注解
(3) 使用注解声明Bean对象的id,默认是类的名称首字母小写
类名 Bean的id名称UserAction userActionUserServiceImpl userServiceImplUserDaoImpl userDaoImpl
(4) 配置扫描的包 <!-- 设置扫描的包 -->
<context:component-scan base-package="com.pers.spring.*"/>
(5) 需要拷贝AOP的包:
spring-aop-4.0.0.RELEASE.jar
(6) 设置扫描的包,包含或者不包含:
<?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-4.0.xsd">     <!-- 设置扫描的包 -->     <context:component-scan base-package="com.atguigu.spring.*"/>     <!--使用context:include-filter指定扫描包时要包含的类-->     <!-- <context:component-scan base-package="com.atguigu.spring.*" use-default-filters="false">          type="annotation" : 表示哪种类型注解应用的Bean需要被扫描          type="assignable" : 采用Bean的类型进行过滤          <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>          <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>     </context:component-scan> -->     <!--使用context:exclude-filter指定扫描包时不包含的类      <context:component-scan base-package="com.atguigu.spring.*">          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>          <context:exclude-filter type="assignable" expression="com.atguigu.spring.component.UserService"/>      </context:component-scan>       --></beans>
7 自动装配注解@Autowired与@Resource
(1) @Autowired
     ① 首先,根据byType进行装配,如果查找到一个,直接装配;
     ② 如果查找到多个相同类型的Bean对象,会再根据byName进行查找。
如果多个Bean对象中有Bean的id与属性名称相同,就直接装配
如果多个Bean对象中没有与Bean的属性名称相同的id,那么,报错。
    ③ 如果希望通过指定的名称id来装配Bean对象,可以借助于@Qualifier注解
    ④ 当查找不到Bean对象,装配不成功,会报错时,希望装配不到Bean对象就不再装配Bean对象了。可以设置@Autowired(required=false)
(2) @Resource
     @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  @Resource装配顺序
   如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
   如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
   如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
   如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

原创粉丝点击