Spring的学习(2)

第1章使用Spring的IOC完成保存客户的操作:

1.1案例需求

需求描述
对于CRM的系统而言,现在有很多的DAO类,比如客户的DAO,联系人DAO等等。客户提出一个需求要开发人员实现一个功能对所有的DAO的类中以save开头的方法实现权限的校验,需要时管理员的身份才可以进行保存操作。

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

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

新建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的类型,对应,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=“setup”destory-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和注解都有(特殊年代产物)
Spring2.0 就有@Autowired注解
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>

2.2Spring的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>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值