Spring 开发的时候可以配置XML也可以用注解开发,
一般情况下使用XML的较多
注解开发的优点就是方便,无论是将类交给Spring管理还是属性注入,都可以直接在当前类上或者方法上,或者属性上,添加注解就可以直接使用,就可以完成类的管理和属性注入
XML的优点是逻辑清晰
两种方式各有优缺点,
在不同情况下选择不同的开发方式,
下面将介绍Spring的注解开发,以及XML和注解的混合开发的案例
一、Spring的IOC的注解开发:普通属性
1、创建一个web项目,引入jar
- 在Spring4的版本注解开发的时候,除了引入基本的开发包以外,还需要引入aop的包。
2、引入Spring的配置文件
(1) 在src下创建applicationContext.xml
(2) 引入约束:使用注解开发需要引入context约束。
约束路径:
spring-framework-4.2.4.RELEASE-dist\spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html
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">
<!-- bean definitions here -->
</beans>
3、创建接口和实现类
package com.itzheng.spring.demo1;
public interface UserDao {
public void save();
}
package com.itzheng.spring.demo1;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAO保存用户的方法执行了。。。。");
}
}
(1)传统方式
@Test
// 传统测试方法
public void demo1() {
UserDao dao = new UserDaoImpl();
dao.save();
}
(2)Spring的IOC的注解方式
- a、开启Spring的组件扫描
使用IOC的注解开发,需要配置组件扫描 component-scan 组件扫描(哪些包【包路径】下的类要使用IOC的注解)
<context:component-scan base-package="com.itzheng.spring.demo1"></context:component-scan>
<?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">
<!-- bean definitions here -->
<!-- Spring的IOC注解的入门 -->
<!-- 使用IOC的注解开发,需要配置组件扫描 component-scan 组件扫描(哪些包【包路径】下的类要使用IOC的注解) -->
<context:component-scan base-package="com.itzheng.spring.demo1"></context:component-scan>
</beans>
- b、在类上添加注解
在要实例化的类上添加注解
用户DAO实现类,要在要实现的类上添加注解
@Component(value = "userDao")
// 或者将value省略
相当于在xml 当中配置<bean id="userDao" class="com.itzheng.spring.demo1.UserDaoImpl"/>
package com.itzheng.spring.demo1;
import org.springframework.stereotype.Component;
//用户DAO实现类,要在要实现的类上添加注解
@Component(value = "userDao") // 或者将value省略 相当于在xml 当中配置<bean id="userDao" class="com.itzheng.spring.demo1.UserDaoImpl"/>
public class UserDaoImpl implements UserDao {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAO保存用户的方法执行了。。。。");
}
}
- c、编写测试类
(UserDao) applicationContext.getBean("userDao");
是通过注解获取到UserDaoImpl的实例对象,通过然后通过多态调用对应的方法
getBean获取Spring当中管理的类
@Test
//Spring的IOC的注解方式
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// (UserDao) applicationContext.getBean("userDao"); 获取到的是UserDaoImpl
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
4、通过注解方式对实现类进行属性设置
设置属性和值
package com.itzheng.spring.demo1;
import org.springframework.stereotype.Component;
public class UserDaoImpl implements UserDao {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAOImpl保存用户的方法执行了。。。。"+name);
}
}
(1)传统方式设置值
@Test
// 传统测试方法
public void demo1() {
UserDaoImpl dao = new UserDaoImpl();
dao.setName("张三");
dao.save();
}
(2)Spring的IOC的注解方式设置值设置属性和值
用户DAO接口的实现类上添加注解,也就是在Impl的类上添加注解
@Component(value = "userDao")
或者将value省略 @Component( "userDao")
相当于在xml 当中配置<bean id="userDao" class="com.itzheng.spring.demo1.UserDaoImpl"/>
也就是工厂可以通过userDao获取到对应的UserDaoImpl对象
注解方式:
使用注解方式,在实现类当中是可以没有set方法的。
两种情况
- a、属性如果提供set方法就将注解加在set方法上
package com.itzheng.spring.demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//用户DAODM实现类,要在要实现的类上添加注解
@Component(value = "userDao") // 或者将value省略 相当于在xml 当中配置<bean id="userDao"
// class="com.itzheng.spring.demo1.UserDaoImpl"/>
public class UserDaoImpl implements UserDao {
private String name;
@Value("李四")
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAOImpl保存用户的方法执行了。。。。"+name);
}
}
- b、属性如果不提供set方法就将注解加在属性上
package com.itzheng.spring.demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//用户DAODM实现类,要在要实现的类上添加注解
@Component(value = "userDao") // 或者将value省略 相当于在xml 当中配置<bean id="userDao" class="com.itzheng.spring.demo1.UserDaoImpl"/>
public class UserDaoImpl implements UserDao {
@Value("李四")
private String name;
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAOImpl保存用户的方法执行了。。。。"+name);
}
}
- c、测试以上两种赋值的效果相同
@Test
//Spring的IOC的注解方式
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// (UserDao) applicationContext.getBean("userDao"); 获取到的是UserDaoImpl
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
二、Spring的IOC的注解开发:注解详解+属性注入
1、@Component:组件
修饰一个类,将这个类交给Spring管理。
这个注解有三个延伸注解(功能类似),用来修饰类的
(1)@Controller:修饰web层的类:
(2)@Service:修饰service层的类:
(3)@Repository:修饰dao层的类:
@Repository是将UserDaoImpl 配置,
工厂可以通过userDao来获取对应的UserDaoImpl 对象的实例,
其他两个作用一样只是修饰的类的层不同
package com.itzheng.spring.demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//用户DAO实现类,要在要实现的类上添加注解
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Value("李四")
private String name;
/*
* public void setName(String name) { this.name = name; }
*/
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAOImpl保存用户的方法执行了。。。。" + name);
}
}
2、属性注入的注解
(1)普通属性
@Value:设置普通属性的值。
(2)对象类型的属性:@Autowired:设置对象类型的属性的值,但是它是按照类型来完成的属性注入。
package com.itzheng.spring.demo1;
public interface UserDao {
public void save();
}
@Value(“李四”)将属性注入到UserDaoImpl 的name当中
package com.itzheng.spring.demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
@Repository("userDao")//
public class UserDaoImpl implements UserDao {
@Value("李四")
private String name;
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("DAOImpl保存用户的方法执行了。。。。" + name);
}
}
创建UserService
package com.itzheng.spring.demo1;
public interface UserService {
public void save();
}
@Service(“UserService”)
// 相当于配置了<bean id="userService" class="com.itzheng.spring.demo1.UserServiceImpl">
在工厂当中通过UserService获取到UserServiceImpl对象的实例
在Service当中调用Dao层,通过注解的方式将Dao注入
UserServiceImpl
@Autowired修饰属性,将属性对应的类,注入到当前类当中
package com.itzheng.spring.demo1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("UserService") // 相当于配置了<bean id="userService"
// class="com.itzheng.spring.demo1.UserServiceImpl">
public class UserServiceImpl implements UserService {
// 注入DAO
@Autowired
private UserDao userDao;
//在Service当中调用Dao层
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserServiceImpl执行了");
userDao.save();
}
}
测试
@Test
// Spring的IOC的注解方式
public void demo3() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// (UserDao) applicationContext.getBean("userDao"); 获取到的是UserDaoImpl
UserService userService = (UserService) applicationContext.getBean("UserService");
userService.save();
}
(3)注意
@Autowired将@Repository修饰的类注入到当前修饰的对象上,
因为这里是继承了UserDao所以,
@Repository修饰的名称不管是什么,
在UserServiceImpl当中的@Autowired修饰的userDao,注入的一定是UserDao的对象的实例,也就是userDaoImpl对象
但是在UserDaoImpl上一定要用@Repository来修饰该类
(4)我们的习惯是安装名称完成属性的注入:必须让@Autowired注解和@Qualifier(value=“”)一起使用来完成安装名称的属性注入
@Qualifier(value=“userDao”)强制按名称来完成属性的注入
@Service("UserService") // 相当于配置了<bean id="userService" class="com.itzheng.spring.demo1.UserServiceImpl">
public class UserServiceImpl implements UserService {
// 注入DAO
@Autowired
@Qualifier(value="userDao")//强制按名称来完成属性的注入
private UserDao userDao;
//在Service当中调用Dao层
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserServiceImpl执行了");
userDao.save();
}
}
(5)@Resource:完成对象类型的属性的注入,按照名称完成属性注入。
@Service("UserService") // 相当于配置了<bean id="userService"
// class="com.itzheng.spring.demo1.UserServiceImpl">
public class UserServiceImpl implements UserService {
// 注入DAO
@Resource(name = "userDao")
private UserDao userDao;
// 在Service当中调用Dao层
@Override
public void save() {
System.out.println("UserServiceImpl执行了");
userDao.save();
}
}
注解可以理解为拆分版的XML和XML的原理相同,所有的注解可以理解为在同一个XML下的配置
三、Bean的其他的注解
1、生命周期的注解:对类进行初始化的注解(在对应初始化方法上进行注解)
通过设置@Service(“customerService”) 修饰一个类,将这个类交给Spring管理。
@PostConstruct :初始化方法 相当于init-method,在工厂获得Spring管理的对象,自动执行其对应的初始化方法
@PreDestroy : 销毁方法 相当于destroy-method=“destroy”,在工厂获得Spring管理的对象,自动执行其对应的销毁方法
package com.itzheng.spring.demo2;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Service;
@Service("customerService")//<bean id="" class="" init-method="init" destroy-method="destroy">
public class CustomerService {
@PostConstruct //相当于init-method,在工厂获得Spring管理的对象,自动执行其对应的初始化方法
public void init() {
System.out.println("CustomerService被初始化了。。。。。");
}
public void save() {
System.out.println("Service的save的方法执行。。。。。");
}
@PreDestroy //相当于destroy-method="destroy",在工厂获得Spring管理的对象,自动执行其对应的销毁方法
public void destroy() {
System.out.println("CustomerService被销毁了。。。。。");
}
}
测试类
package com.itzheng.spring.demo2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo2 {
@Test
public void demo1() {
//通过工厂获取xml文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//getBean获取Spring当中管理的类
CustomerService customerService = (CustomerService)applicationContext.getBean("customerService");
System.out.println(customerService);
applicationContext.close();//关闭工厂
}
}
2、Bean作用的注解范围
@Scope:作用范围
Scope的取值:
singleton:默认单例
prototype:多例
request:
session:
globalsession:
(1)在customerService上设置@Scope注解
在测试类当中创建两个CustomerService 实例对象
public class SpringDemo2 {
@Test
public void demo1() {
// 通过工厂获取xml文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// getBean获取Spring当中管理的类
CustomerService customerService1 = (CustomerService) applicationContext.getBean("customerService");
System.out.println(customerService1);
CustomerService customerService2 = (CustomerService) applicationContext.getBean("customerService");
System.out.println(customerService2);
applicationContext.close();// 关闭工厂
}
}
结果证明两个类是同一个对象,也就是说明Scope的取值默认单例
(2)当@Scope(“singleton”)设置该对象交给Spring的时候是单例创建对象
结果和默认值想效果相同
(3)当@Scope(“prototype”)设置该对象交给Spring的时候是多例创建对象
证明创建的是两个对象,即为多例模式
四、IOC的XML和注解开发比较
1、XML和注解的比较
适用场景
XML:可以适用任何场景。
结构清晰,维护方便。
注解:有些地方用不了,(这个类不是自己提供的,原码当中提的属性)
纯注解(SSH)
开发方便。(编写类,在类上加注解,将类交给Spring管理,在其他地方通过工厂获得该类、属性注入直接在已经交给Spring管理的类当中,通过标签将属性注入到对应定义标签修饰的属性当中)
五、XML和注解开发的整合
1、XML管理Bean、注解完成属性注入。(在有扫描器的情况下)
编写ProductDao 类
package com.itzheng.spring.demo3;
public class ProductDao {
public void save() {
System.out.println("ProductDao的save方法执行了。。。。");
}
}
编写OrderDao
package com.itzheng.spring.demo3;
public class OrderDao {
public void save() {
System.out.println("OrderDao的save方法执行了。。。。");
}
}
编写ProductService方法并且设置对应的属性
package com.itzheng.spring.demo3;
public class ProductService {
private ProductDao productDao;
private OrderDao orderDao;
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void save() {
System.out.println("ProductService的save方法执行了。。。。。");
productDao.save();
orderDao.save();
}
}
将三个类交给Spring管理,productDao和orderDao并将注入到productService类当中
<?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">
<!-- bean definitions here -->
<!-- Spring的IOC注解的入门 -->
<!-- 扫描是为了扫描类上的注解 -->
<!-- 使用IOC的注解开发,需要配置组件扫描 component-scan 组件扫描(哪些包【包路径】下的类要使用IOC的注解) -->
<context:component-scan
base-package="com.itzheng.spring"></context:component-scan>
<bean id="productService" class="com.itzheng.spring.demo3.ProductService">
<property name="productDao" ref="productDao"></property>
<property name="orderDao" ref="orderDao"></property>
</bean>
<bean id="productDao" class="com.itzheng.spring.demo3.ProductDao">
</bean>
<bean id="orderDao" class="com.itzheng.spring.demo3.OrderDao">
</bean>
</beans>
编写测试类
package com.itzheng.spring.demo3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo3 {
@Test
public void demo1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ProductService productService = (ProductService) applicationContext.getBean("productService");
productService.save();
}
}
2、使用XML和注解整合的方式(类的管理通过XML的方式,属性注入通过注解的方式) 没有扫描器的情况下(类上没有注解)
通过注解注入属性则不需要,提供set方法
并且设置context:annotation会自动根据需要注入的类当中注解,进行属性的注入
<context:annotation-config></context:annotation-config>
自动将对应类交给Spring,自动将对应的属性注入到对象当中
<?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">
<!-- bean definitions here -->
<!-- Spring的IOC注解的入门 -->
<!-- 使用IOC的注解开发,需要配置组件扫描 component-scan 组件扫描(哪些包【包路径】下的类要使用IOC的注解) -->
<!-- 在沒有扫描的情况下,使用属性注入的注解 @Resource,@Value,@Autowired,@Qulifier-->
<context:annotation-config></context:annotation-config>
<bean id="productService" class="com.itzheng.spring.demo3.ProductService"></bean>
<bean id="productDao" class="com.itzheng.spring.demo3.ProductDao"> </bean>
<bean id="orderDao" class="com.itzheng.spring.demo3.OrderDao"> </bean>
</beans>
在@Resource上设置注入的属性