spring day02——注解的使用

  1. IoC容器装配Bean_基于注解配置方式
    1. Bean的定义(注册) -- 扫描机制

新建web项目:spring4_d02_c02

 

第一步:

导入jar包(4个核心包+2个日志包),

导入log4j.properties,

导入applicationContext.xml

Spring XML开发和注解开发 导入jar包是相同的

 

第二步: 编写Service和DAO 的注册

        xml做法 : <bean id=”customerService” class=”…” />,用<bean>的方式创建对象

         注解做法 : spring2.5引入 @Component 注解 如果放置到类的上面,相当于在spring容器中定义<bean id=”” class=””>

创建包:com.igeek.ioc

创建类:CustomerService.java类

/**

 * @Component注解放置到类上

 * 相当于spring容器中定义:<bean id="customerService" class="com.igeek.ioc.CustomerService">

 * 其中id属性默认bean的名字是类名的小写

 * ——————————————————————————————————————————————————————

 * @Component(value="customer")//自定义bean的名字

 * 相当于spring容器中定义:<bean id="customer" class="com.igeek.ioc.CustomerService">

 * ——————————————————————————————————————————————————————

 */

@Component(value="customer")

public class CustomerService {

   

    //保存业务方法

    public void save(){

       System.out.println("CustomerService业务层被调用了。。。");

    }

 

}

 

第三步: 配置注解开启和注解Bean的扫描。配置的示例如下:配置applicationContext.xml

参考:

spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html,搜索context关键字即可

<?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:专门扫描含有@Component注解的类,自动将其作为bean

           base-package:要扫描包的路径,包含子包,com.igeek.ioc表示子包下的所有类定义注解都有效

           注解扫描配置的时候,会自动开启注解功能

    -->

    <context:component-scan base-package="com.igeek.ioc"/>

   

      

</beans>

         引入context 名称空间 :

 

【注意】Spring的所有名称空间都需要基于Beans的名称空间。

引入后:

<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">

 

配置本地提示关联,配置eclipse的XML Catalog Element:

 

第四步:测试:

public class SpringTest {

 

    @Test

    public void test(){

       //spring容器

       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

       //获取bean

       CustomerService customerService=(CustomerService) applicationContext.getBean("customer");

       customerService.save();

      

    }

}

 

这里:如果抛出异常:

说明spring4缺少aop的包,需要导入

【扩展优化】:

衍生注解的问题

实际开发中,使用的是@Component三个衍生注解(“子注解”)

子注解的作用:有分层的意义(分层注解)。

Spring3.0为我们引入了组件自动扫描机制,它可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。

除了@Component外,Spring提供了3个功能基本和@Component等效的注解

功能介绍

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

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

@Repository用于标注数据访问组件,(如DAO层组件)。

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

 

第一步:

修改CutomerService.java

//@Component(value="customer")//注释掉

@Service(value="customer")

public class CustomerService {

   

    //保存业务方法

    public void save(){

       System.out.println("CustomerService业务层被调用了。。。");

    }

 

}

创建CustomerDao.java

//持久层

@Repository("customerDao")

public class CustomerDao {

   

    public void save(){

       System.out.println("CustomerDao层被调用了");

    }

 

}

【抛出问题】:如果将Dao注入到Service呢?即使用Service类调用Dao类?

回顾:如果使用xml的配置,那么可以使用setter方法进行注入

<bean id=”” class=””>

    <property name=”” ref=””></property>

</bean>

让我们接着往下学习。

 Bean属性的依赖注入

 简单数据类型依赖注入(了解)

Spring3.0后,提供 @Value注解,可以完成简单数据的注入

//@Component(value="customer")

@Service(value="customer")

public class CustomerService {

    //简单类型的成员变量

    @Value("Rose")//参数的值简单类型

    private String name="Jack";

   

    //保存业务方法

    public void save(){

       System.out.println("CustomerService业务层被调用了。。。");

       System.out.println("name:"+name);

    }

}

 复杂类型数据依赖注入

下面完成,将Dao类的对象注入到Service类进行使用。

注解实现属性依赖注入,将注解加在setXxx方法上 或者 属性定义上 !(任选其一,省代码了)

 

第一种: 使用@Value 结合SpEL  ---- spring3.0 后用

//@Component(value="customer")

@Service(value="customer")

public class CustomerService {

    //简单类型的成员变量

    @Value("Rose")//参数的值简单类型

    private String name="Jack";

   

    //在属性声明上面注入,底层自动还是生成setCustomerDao()

    //第一种: 使用@Value 结合SpEL  ---- spring3.0 后用

    //其中customerDao表示<bean>节点id的属性值

    /**第一种: 使用@Value 结合SpEL  ---- spring3.0 后用*/

    //@Value(value="#{customerDao}")

    private CustomerDao customerDao;

   

    @Value(value="#{customerDao}")

    public void setCustomerDao(CustomerDao customerDao) {

       this.customerDao = customerDao;

    }

   

    //保存业务方法

    public void save(){

       System.out.println("CustomerService业务层被调用了。。。");

       System.out.println("name:"+name);

       customerDao.save();

    }

 

}

第二种:使用@Autowired 结合 @Qualifier

         单独使用@Autowired ,表示按照类型注入,会到spring容器中查找CustomerDao的类型,对应<bean class=””>,class的属性值,如果找到,可以匹配。

    //第二种:使用spring的@Autowired

    @Autowired//默认按照类型注入

    private CustomerDao customerDao;

         使用@Autowired + @ Qualifier 表示按照名称注入,会到spring容器中查找customerDao的名称,对应<bean id=””>,id的属性值,如果找到,可以匹配。

   //第二种:使用spring的@Autowired 结合 @Qualifier

    @Autowired//默认按照类型注入的

    @Qualifier("customerDao")//必须配合@Autowired注解使用,根据名字注入

    private CustomerDao customerDao;

 

第三种: JSR-250标准(基于jdk) 提供注解@Resource

    单独使用@Resource注解,表示先按照名称注入,会到spring容器中查找customerDao的名称,对应<bean id=””>,id的属性值,如果找到,可以匹配。

如果没有找到,则会按照类型注入,会到spring容器中查找CustomerDao的类型,对应<bean class=””>,class的属性值,如果找到,可以匹配,如果没有找到会抛出异常。

    //第三种: JSR-250标准(jdk) 提供@Resource

    @Resource//默认按照名称进行匹配,再按照类型进行匹配

    private CustomerDao customerDao;

 

如果@Resource注解上添加name名称

    使用@Resource注解,则按照名称注入,会到spring容器中查找customerDao的名称,对应<bean id=””>,id的属性值,如果找到,可以匹配。

    如果没有找到,抛出异常。

    //第三种: JSR-250标准(jdk) 提供@Resource

    @Resource(name="customerDao")//只能按照customerDao名称进行匹配

    private CustomerDao customerDao;

第四种: JSR-330标准(jdk) 提供 @Inject (麻烦点)

         需要先导入 javax.inject 的 jar ,在课前资料中查找。

    使用@Inject注解,则按照类型注入,

    //第四种: JSR-330标准(jdk) 提供 @Inject ,配合@Named注解

    @Inject//默认按照类型注入

    private CustomerDao customerDao;

    使用@inject和@Named注解,则按照名称注入

    //第四种: JSR-330标准(jdk) 提供 @Inject ,配合@Named注解

    @Inject//默认按照类型注入

    @Named("customerDao")//按照名字注入,必须配合@Inject使用

    private CustomerDao customerDao;

 

 

 

 Bean的初始化和销毁

使用注解定义Bean的初始化和销毁

    Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。

回顾配置文件的写法:<bean id=“foo” class=“...Foo” init-method=setupdestory-method=teardown/>

注解的写法:

(1)当bean被载入到容器的时候调用setup ,

注解方式如下: 

@PostConstruct

初始化

(2)当bean从容器中删除的时候调用teardown(scope= singleton有效)

注解方式如下:

@PreDestroy 

销毁

 

使用 @PostConstruct 注解, 标明初始化方法 ---相当于 init-method 指定初始化方法

使用 @PreDestroy 注解, 标明销毁方法  ----相当于 destroy-method 指定对象销毁方法

第一步:创建类:LifeCycleBean.java,定义构造方法、初始化的方法、销毁的方法。

//测试生命周期过程中的初始化和销毁bean

@Component("lifeCycleBean")

public class LifeCycleBean {

   

    public LifeCycleBean() {

       System.out.println("LifeCycleBean构造器调用了");

    }

   

    //初始化后自动调用方法:方法名随意,但也不能太随便,一会要配置

    @PostConstruct//初始化的方法

    public void init(){

       System.out.println("LifeCycleBean-init初始化时调用");

    }

   

    //bean销毁时调用的方法

    @PreDestroy

    public void destroy(){

       System.out.println("LifeCycleBean-destroy销毁时调用");

    }

 

}

 

第二步:配置文件,配置spring容器applicationContext.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:专门扫描含有@Component注解的类,自动将其作为bean

    base-package:要扫描包的路径,包含子包,com.igeek.ioc表示子包下的所有类定义注解都有效

    注解扫描配置的时候,会自动开启注解功能

    -->

    <context:component-scan base-package="com.igeek.ioc"/>

   

      

</beans>

第三步:使用SpringTest.java完成测试

@Test

    public void testLifeCycle() throws Exception{

       //spring容器

       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

       //单例;此时初始化的方法已经被调用

       LifeCycleBean lifeCycleBean = (LifeCycleBean)applicationContext.getBean("lifeCycleBean");

        //方案一:

        //((ClassPathXmlApplicationContext)applicationContext).close();

        //方案二:

       //反射的机制调用close方法。

       //接口只是引用了一个对象。对象本身有这个方法。

       //目标:通过接口引用,调用对象本来的拥有的方法

       //1。获取对象具体类的某个方法:参数1方法名,参数2:方法里面的参数类型

       Method method = applicationContext.getClass().getMethod("close");

       //参数1:拥有该方法的对象的名字,参数2:方法里面的参数的值

       method.invoke(applicationContext);

      

    }

注意:如果要执行对象的销毁方法

         条件一: 单例Bean (在容器close时,单例Bean才会执行销毁方法

         条件二: 必须调用容器 close 方法

 

 Bean的作用域

通过@Scope注解,指定Bean的作用域(默认是 singleton 单例)

回顾:XML的方式<bean id=”” class=”” scope=”prototype”>

 

//测试生命周期过程中的初始化和销毁bean

@Component("lifeCycleBean")

//@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)

@Scope("prototype")//默认是单例(singleton),更改为多例(prototype)

public class LifeCycleBean {

 

}

 

测试:

    @Test

    public void testLifeCycleScope() throws Exception{

       //spring容器

       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

       //单例;此时初始化的方法已经被调用

       LifeCycleBean lifeCycleBean1 = (LifeCycleBean)applicationContext.getBean("lifeCycleBean");

       LifeCycleBean lifeCycleBean2 = (LifeCycleBean)applicationContext.getBean("lifeCycleBean");

       System.out.println(lifeCycleBean1);

       System.out.println(lifeCycleBean2);

    }

 XML和注解混合配置 (重点)

一个项目中XML和注解都有(特殊年代产物)

  1. Spring2.0 就有@Autowired注解
  2. Spring2.5 之后才有@Component注解

 

使用

XML 完成Bean定义

注解 完成Bean属性注入

 

创建包:com.igeek.ioc.mixed

第一步:使用XML的方式完成Bean的定义

创建applicationContext-mixed.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">

   

    <!-- xml方式定义bean -->

    <bean id="productDao" class="com.igeek.ioc.mixed.ProductDao"/>

    <bean id="productService" class="com.igeek.ioc.mixed.ProductService"/>

   

    <!-- 需要单独开启注解功能 -->

    <context:component-scan base-package="com.igeek.ioc"></context:component-scan>

</beans>

第二步:注解完成注入

(1)创建ProductDao类

//产品的数据层

public class ProductDao {

   

    public void save(){

       System.out.println("查询保存到数据口--数据层调用了");

    }

 

}

(2)创建ProductService类

//产品的业务层

public class ProductService {

   

    //注入dao

    //强调:注入必须是bean注入bean

    @Autowired

    private ProductDao productDao;

   

    //产品的保存

    public void save(){

       System.out.println("产品保存了,--业务层");

       //调用dao

       productDao.save();

    }

 

}

 

测试类:

public class SpringTest {

 

    @Test

    public void test(){

       //spring容器

       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-mixed.xml");

       //获取bean

       ProductService productService=(ProductService) applicationContext.getBean("productService");

       productService.save();

      

    }

   

}

 

备注:这里配置 <context:component-scan base-package="com.igeek.ioc"></context:component-scan>

才能使用 @PostConstruct @PreDestroy @Autowired @Resource等注解

<!-- 需要spring容器中单独开启注解功能,扫描com.igeek.ioc包及其子包中所有类都有效,类中都可以使用注解 -->

    <context:component-scan base-package="com.igeek.ioc"></context:component-scan>

 

 

    1. Spring的junit测试集成

Spring提供spring-test-4.2.4.RELEASE.jar 可以整合junit。

优势:可以简化测试代码(不需要手动创建上下文,即手动创建spring容器)

 

使用spring和junit集成

第一步:新建项目导入junit 开发包

第二步:导入spring-test-4.2.4.RELEASE.jar

第三步: 创建包com.igeek.test,创建类SpringTest

通过@RunWith注解,使用junit整合spring

         通过@ContextConfiguration注解,指定spring容器的位置

//目标:测试一下spring的bean的某些功能

@RunWith(SpringJUnit4ClassRunner.class)//junit整合spring的测试//立马开启了spring的注解

@ContextConfiguration(locations="classpath:applicationContext.xml")//加载核心配置文件,自动构建spring容器

public class SpringTest {

    //使用注解注入要测试的bean

    @Autowired

    private HelloService helloService;

   

    @Test

    public void testSayHello(){

       //获取spring容器

//     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

       //从spring容器中获取bean对象

//     HelloService helloService=(HelloService)applicationContext.getBean("helloService");

       //测试业务功能

       helloService.sayHello();

      

    }

}

上述代码表示:在测试类运行前的初始化的时候,会自动创建ApplicationContext对象

 

第四步: 通过@Autowired注解,注入需要测试的对象

在这里注意2点:

  1. 将测试对象注入到测试用例中
  2. 测试用例不需要配置<context:annotion-config/>,或者是<context:component-scan base-package="com.igeek"/>,因为使用测试类运行的时候,会自动启动注解的支持。

//使用注解注入要测试的bean

    @Autowired

    private HelloService helloService;

 

 

第五步:调用测试方法完成测试

    @Test

    public void testSayHello(){

       helloService.sayHello();

    }

 

第六步:在applicationContext.xml中添加:

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:p="http://www.springframework.org/schema/p"

       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.igeek.ioc"/>

    <!-- 创建Service -->

    <bean id="helloService" class="com.igeek.test.HelloService"></bean>

</beans>

猜你喜欢

转载自blog.csdn.net/weixin_44383366/article/details/86654809