IoC容器装配Bean_基于注解配置方式

spring IOC容器 Bean 管理——基于注解方式

Bean的定义(注册) – 扫描机制

第一步:引入依赖
pom.xml

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.4</version>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        

导入log4j.properties

log4j.rootLogger=INFO,A1
log4j.logger.org.apache=INFO
log4j.appender.A1.Target=System.err
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

导入applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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">

    <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
 
   <!-- 开启spring的注解功能 :让注解有效了,识别注解-->
    <context:annotation-config/>

    <!-- 配置注解扫描
                context:component-scan:专门扫描含有@Component注解的类,自动将其作为bean
                base-package:要扫描包的路径,包含子包,cn.itcast.spring表示子包下的所有类定义注解都有效
                注解扫描配置的时候,会自动开启注解功能
        -->
    <context:component-scan base-package="cn.itcast.spring"/>
</beans>

第二步: 编写Service和DAO

  • xml做法 : <bean id=”customerService” class=”…” />,用<bean>的方式创建对象
  • 注解做法 : spring2.5引入 @Component 注解 如果放置到类的上面,相当于在spring容器中定义

创建类:CustomerService.java类

/**
 * @Component注解放置到类上
 * 相当于spring容器中定义:<bean id="customerService" class="cn.itcast.spring.a_ioc.CustomerService">
 * 其中id属性默认bean的名字是类名的小写
 * ——————————————————————————————————————————————————————
 * @Component(value="customerService")//自定义bean的名字
 * 相当于spring容器中定义:<bean id="customer" class="cn.itcast.spring.a_ioc.CustomerService">
 * ——————————————————————————————————————————————————————
 */
@Component(value="customerService")
public class CustomerService {
	//保存业务方法
	public void save(){
		System.out.println("CustomerService业务层被调用了。。。");
	}
}

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

在这里插入图片描述
第四步:测试:

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest2 {
    @Test
    public void test(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean
        CustomerService customerService=(CustomerService) applicationContext.getBean("customerService");
        customerService.save();
    }
}

在这里插入图片描述

扩展优化:

1.注解扫描配置
在配置包扫描的时候,spring会自动开启注解功能,所以,注解开启功能可以不配置。
即去掉:<context:annotation-config/>
因为<context:componet-scan> 具有 <context:annotation-config> 作用 !

2.衍生注解的问题
实际开发中,使用的是@Component三个衍生注解(“子注解”)
子注解的作用:有分层的意义(分层注解)。

Spring3.0为我们引入了组件自动扫描机制,它可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。
除了@Component外,Spring提供了3个功能基本和@Component等效的注解
功能介绍
@Service用于标注业务层组件、(如Service层)
@Controller用于标注控制层组件(如struts中的action层,springMVC中的controller)
@Repository用于标注数据访问组件,(如DAO层组件)。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

第一步:
修改CutomerService2.java

package cn.itcast.spring;

import org.springframework.stereotype.Service;

@Service(value = "customerService2")
public class CustomerService2 {
    //保存业务方法
    public void save(){
        System.out.println("CustomerService2业务层被调用了。。。");
    }
}



创建CustomerDao.java

package cn.itcast.spring;

import org.springframework.stereotype.Repository;
//持久层
@Repository("customerDao")
public class CustomerDao {
    public void save(){
        System.out.println("CustomerDao层被调用了");
    }
}

问题:如果将Dao注入到Service呢?

回顾:如果使用xml的配置,那么可以使用setter方法进行注入
<bean id=”” class=””>
    <property name=”” ref=””></property>
</bean>

CustomerService.java

@Service(value = "customerService2")
public class CustomerService2 {
    //保存业务方法
    public void save(){
        System.out.println("CustomerService2业务层被调用了。。。");
    }

  public void setCustomerDao(CustomerDao customerDao) {
    }
}

      <bean id="customerDao" class="cn.itcast.spring.CustomerDao"/>
        <bean id="customerService" class="cn.itcast.spring.CustomerService">
        <property name="customerDao" ref="customerDao"></property>
        </bean>

Bean属性的依赖注入

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

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

package cn.itcast.spring;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service(value = "customerService2")
public class CustomerService2 {
    //简单类型的成员变量
    @Value("Rose")//参数的值简单类型
    private String name="Jack";

    //保存业务方法
    public void save(){
        System.out.println("CustomerService业务层被调用了。。。");
        System.out.println("name:"+name);
    }
}

测试

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest2 {
    @Test
    public void test(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean
        CustomerService2 customerService=(CustomerService2) applicationContext.getBean("customerService2");
        customerService.save();
    }
}

在这里插入图片描述

复杂类型数据依赖注入

下面完成,将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("#{customerDao}")
	private CustomerDao customerDao;
	
	//保存业务方法
	public void save(){
		System.out.println("CustomerService业务层被调用了。。。");
		System.out.println("name:"+name);
		customerDao.save();
	}
}

测试

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest2 {
    @Test
    public void test(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean
        CustomerService customerService=(CustomerService) applicationContext.getBean("customerService");
        customerService.save();
    }
}

在这里插入图片描述

在实际开发过程中,第二种方式用的最多(推荐!)

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

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

    //第二种:使用spring的@Autowired
	@Autowired//默认按照类型注入
	private CustomerDao customerDao;

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

	//第二种:使用spring的@Autowired 结合 @Qualifier
	@Autowired//默认按照类型注入的
	@Qualifier("customerDao")//必须配合@Autowired注解使用,根据名字注入
	private CustomerDao customerDao;

在这里插入图片描述

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

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

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

	//第三种: JSR-250标准(jdk) 提供@Resource 
	@Resource//默认先按照名称进行匹配,再按照类型进行匹配
	private CustomerDao customerDao;

如果@Resource注解上添加name名称
使用@Resource注解,则按照名称注入,会到spring容器中查找customerDao的名称,对应,id的属性值,如果找到,可以匹配。如果没有找到,抛出异常。

  //第三种: JSR-250标准(jdk) 提供@Resource 
	@Resource(name="customerDao")//只能按照customerDao名称进行匹配
	private CustomerDao customerDao;

第四种: JSR-330标准(基于jdk) 提供注解@Inject(麻烦,需要额外导包)

        <dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

在这里插入图片描述

Bean的初始化和销毁

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

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

回顾配置文件的写法:<bean id=“foo” class=“…Foo” init-method=“setup”destroy-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销毁时调用");
	}
}

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

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.lang.reflect.InvocationTargetException;

public class SpringTest3 {
    @Test
    public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ApplicationContext ac =  new ClassPathXmlApplicationContext("applicationContext.xml");
        
        /*CustomerService customerService = (CustomerService) ac.getBean("customerService");
		
		customerService.save();*/

        //((AbstractApplicationContext) ac).close();

        //反射:
        ac.getClass().getMethod("close").invoke(ac);
    }
}

在这里插入图片描述

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

  • 条件一: 单例Bean (在容器close时,单例Bean才会执行销毁方法
  • 条件二: 必须调用容器 close 方法

Bean的作用域

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

//测试生命周期过程中的初始化和销毁bean
@Component("lifeCycleBean")
//@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope("prototype")//默认是单例(singleton),更改为多例(prototype)
public class LifeCycleBean {

}

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

一个项目中XML和注解都有(时代变迁,夹缝中的产物)

  • Spring2.0 就有@Autowired注解
  • Spring2.5 之后才有@Component注解
使用
XML 完成Bean定义
注解 完成Bean属性注入 

第一步:
(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();
	}
}

第二步:使用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="cn.itcast.spring.ProductDao"/>
	<bean id="productService" class="cn.itcast.spring.ProductService"/>
	
	<!-- 需要单独开启注解功能 -->
	<context:annotation-config/>
</beans>

测试

package cn.itcast.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class SpringTest4 {
    @Test
    public void test(){
        //spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean
        ProductService productService=(ProductService) applicationContext.getBean("productService");
        productService.save();
    }
}

在这里插入图片描述

备注:
这里配置 <context:annotation-config>
才能使用 @PostConstruct @PreDestroy @Autowired @Resource

<!-- 需要在spring容器中单独开启注解功能 -->
	<context:annotation-config/>

提示:
因为采用注解开发时,<context:component-scan> 具有<context:annotation-config>的功能 。
如果没有配置注解扫描,需要单独配置 <context:annotation-config>, 才能使用注解注入!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值