xml配置方式实现IOC
使用IOC,要导入四个核心容器的包(Beans,Core,Context,SpEL)以及两个日志记录包,
Spring配置文件名为applicationContext.xml(可以自定义), 约束在spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html这个文件中找。
IOC和DI
/**
* 接口与接口实现
*
*/
public interface UserService {
public void save1();
public void save2();
}
public class UserServiceImpl implements UserService {
private String name;
@Override
public void save1() {
System.out.println("UserService执行了");
}
@Override
public void save2(){
System.out.println("UserService执行了" + name);
}
public void setName(String name) {
this.name = name;
}
}
在applicationContext.xml中配置:
class值为类的全路径(包名+类名)
<!--
bean标签中还有个name属性
id: 使用了约束中的唯一约束。
里面不能出现特殊字符
name:没有使用约束中的唯一约束(理论上可以出现重复的,但实际开发中不能出现)。
里面可以出现特殊字符。
-->
<bean id="UserService" class="demo01.UserServiceImpl">
<property name="name" value="张三"/>
</bean>
@Test
/**
* Spring方式调用-----IOC
*
* 在配置文件中配置接口和接口的实现,然后在这里读取xml文件根据接口名字得到实现类
*/
public void test1(){
//创建Spring 工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("UserService");
userService.save1();
}
@Test
/**
* Spring--DI(依赖注入)
* DI前提:实现IOC,即这个类要交给Spring去管理
* DI实例:接口的实现中有个name属性,可以在xml中用property标签配置它的值,实现类中必须
* 要有set方法。
*
*/
public void test2(){
//创建Spring 工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("UserService");
userService.save2();
}
applicationContext
application是个接口,有FileSystemXmlApplicationContext,ClassPathXmlApplicationContext两个最终实现类
ClassPathXmlApplicationContext加载的是类路径下的配置文件,即src下的路径
FileSystemXmlApplicationContext加载的是文件系统下的配置文件,即磁盘中的位置
@Test
public void test3(){
//创建Spring 工厂
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("UserService");
System.out.println(22);
userService.save1();
}
Spring生命周期及Bean的作用范围
public interface CustomerDao {
public void init();
public void save();
public void destory();
}
public class CustomerDaoImpl implements CustomerDao{
public void init(){
System.out.println("CustomerDaoImpl类开始初始化");
}
@Override
public void save() {
System.out.println("CustomerDaoImpl执行了");
}
public void destory(){
System.out.println("CustomerDaoImpl类被销毁");
}
}
在xml中配置:
<bean id="CustomerDao" class="demo02.CustomerDaoImpl" init-method="init" destroy-method="destory" scope=""></bean>
scope即作用范围的配置,
singleton:默认的,Spring会采用单例模式创建这个对象
prototype:多例模式创建(Struts2与Spring整合会用到)
request:应用在web项目中,Spring创建这个类以后,将这个类存到request范围中
session:应用在web项目中,Spring创建这个类以后,将这个类存到session范围中
@Test
/**
* 生命周期配置
* 在配置文件的bean标签中添加 init-method="init" destroy-method="destory"来配置bean的生命周期(注意方法名不要括号)
* 然后在CustomerDaoImpl类中写这两个方法(要想执行销毁方法必须是单例,即没有在bean中配置scope="prototype")
*/
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerDaoImpl customerDaoImpl = (CustomerDaoImpl)applicationContext.getBean("CustomerDao");
customerDaoImpl.save();
//只有执行了close()方法才会执行destory方法,close()方法是子类中方法所以用ClassPathXmlApplicationContext
applicationContext.close();
}
@Test
/**
* bean作用范围的配置
* 在配置文件的bean标签中添加scope属性,
* singleton为单例,prototype为多例
*/
public void test2(){
}
Bean实例化的方式
/**
* 无参数构造方法
*/
public class Bean1 {
public Bean1() {
super();
System.out.println("Bean1的无参数的构造方法执行了...");
}
}
/**
* 静态工厂实例化
*/
public class Bean2 {
}
public class Bean2Factory {
public static Bean2 createBean2(){
System.out.println("Bean2Factory中方法执行了...");
return new Bean2();
}
}
/**
* 实例工厂实例化
*/
public class Bean3 {
}
public class Bean3Factory {
public Bean3 createBean3(){
System.out.println("Bean3的实例工厂执行了...");
return new Bean3();
}
}
在xml中配置:
<!-- 无参数构造方法 -->
<bean id="bean1" class="demo03.Bean1"></bean>
<!-- 静态工厂实例化 -->
<bean id="bean2" class="demo03.Bean2Factory" factory-method="createBean2"/>
<!-- 实例工厂实例化 -->
<bean id="bean3Factory" class="demo03.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"></bean>
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
System.out.println(bean2);
Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
System.out.println(bean3);
}
属性注入,p名称空间,SpEL
构造方法方式的属性注入:
public class Car1 {
private String name;
private Double price;
public Car1(String name, Double price) {
super();
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Car [name=" + name + ", price=" + price + "]";
}
}
<!-- 构造方法方式 -->
<bean id="Car1" class="demo04.Car1">
<constructor-arg name="name" value="宝马"></constructor-arg>
<constructor-arg name="price" value="800000"></constructor-arg>
</bean>
public void demo1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car1 car1 = (Car1)applicationContext.getBean("Car1");
System.out.println(car1);
}
set方法设置普通属性:
public class Car2 {
private String name;
private Double price;
public void setName(String name) {
this.name = name;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Car [name=" + name + ", price=" + price + "]";
}
}
普通设置方法:
<bean id="Car2" class="demo04.Car2">
<property name="name" value="奔驰"></property>
<property name="price" value="1000000"></property>
</bean>
使用p名称空间(2.5以后):
约束中引入:xmlns:p="http://www.springframework.org/schema/p"
<bean id="Car2" class="demo04.Car2" p:name="奔驰" p:price="1000000">
</bean>
使用SpEL(3.0以后):
SpEL中都用value,不用ref,
<bean id="Car2" class="demo04.Car2">
<property name="name" value="#{'奥迪'}"></property>
<property name="price" value="#{500000}"></property>
</bean>
public void demo2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car2 car2 = (Car2)applicationContext.getBean("Car2");
System.out.println(car2);
}
set方法设置对象类型属性:
public class Person {
private String name;
private Car2 car2;
public void setName(String name) {
this.name = name;
}
public void setCar2(Car2 car2) {
this.car2 = car2;
}
@Override
public String toString() {
return "Person [name=" + name + ", car2=" + car2 + "]";
}
}
普通设置方法:
<bean id="Person" class="demo04.Person">
<property name="name" value="张三"></property>
<property name="car2" ref="Car2"></property>
</bean>
使用p名称空间(2.5以后):
约束中引入:xmlns:p="http://www.springframework.org/schema/p"
<bean id="Person" class="demo04.Person" p:name="张三" p:car2-ref="Car2">
</bean>
使用SpEL(3.0以后):
SpEL中都用value,不用ref,
<bean id="Person" class="demo04.Person">
<property name="name" value="#{'张三'}"></property>
<property name="car2" value="#{Car2}"></property>
</bean>
public void demo(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person)applicationContext.getBean("Person");
System.out.println(person);
}
集合属性注入
public class CollectionBean {
private String[] strs;
private List<String> list;
private Set<String> set;
private Map<String, String> map;
public void setStrs(String[] strs) {
this.strs = strs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String toString() {
return "CollectionBean [strs=" + Arrays.toString(strs) + ", list=" + list + ", set=" + set + ", map=" + map
+ "]";
}
}
添加配置:
<bean id="CollectionBean" class="demo05.CollectionBean">
<property name="strs">
<list>
<value>休斯顿</value>
<value>爱琴海</value>
<value>维也纳</value>
</list>
</property>
<property name="list">
<list>
<value>北京市</value>
<value>上海市</value>
<value>西虹市</value>
</list>
</property>
<property name="set">
<set>
<value>天津市</value>
<value>重庆市</value>
<value>深圳市</value>
</set>
</property>
<property name="map">
<map>
<entry key="德国" value="不莱梅"/>
<entry key="英国" value="英格兰"/>
<entry key="美国" value="华盛顿"/>
</map>
</property>
</bean>
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("CollectionBean");
System.out.println(collectionBean);
}
注解方式实现IOC
还是在spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html这个文件中找到context的约束
注解开发相对xml开发多了一个aop的jar包
在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">
<!-- 使用IOC的注解开发,配置组件扫描(哪些包下的类使用IOC的注解) -->
<context:component-scan base-package="demo1,demo2"/>
</beans>
如果使用xml和注解混合开发,比如类是用的bean标签来交给Spring管理,上面没有@Component注解,但属性注入用的@Resource,@Value等注解时, 这时可以不用包扫描,因为扫描是为了扫描类上面的注释,就要加上下面的:
<?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 -->
<!-- 使用IOC的注解开发,配置组件扫描(哪些包下的类使用IOC的注解) -->
<!-- <context:component-scan base-package="demo1,demo2"/> -->
<!-- 在没有扫描的情况下,使用属性注入的注解:@Resource,@Value -->
<context:annotation-config/>
</beans>
类及属性注入的注解
@Component注解修饰一个类,表示将这个类交给Spring管理,它的衍生注解有@Controller,@Service,@Repository,相当于说 @Component是一个统称,Spring把它细分成三个注解,分别作用于:web层,service层,dao层。
@Value注解设置普通属性
public interface UserDao {
public void save();
}
@Component("UserDao")//相当于:<bean id="UserDao" class="demo1.UserDaoImpl"> </bean>
public class UserDaoImpl implements UserDao {
//如果name属性没有set方法,@Value("张三")就写在这,如果有就写在set方法上
private String name;
@Value("张三")
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("dao中保存用户的方法执行了" + name);
}
}
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao)applicationContext.getBean("UserDao");
userDao.save();
}
@Autowired用来设置对象类型的属性的值,但是是按照类型完成的注入,习惯按名称注入,所以加一个@Qualifier注解,后面的value值为别的类的注解的名称,必须一致
@Autowired,@Qualifier这两个注解必须一起使用,Spring中还可以用@Resource完成对象类型注解,因为Spring实现了JSR-250规范
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
//注入Dao
/**
* @Autowired
* @Qualifier(value="UserDao")//此处的value值必须与UserDao实现类的@Component注解值一致,
*/
@Resource(name="UserDao")
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
}
/**
* Spring的IOC对象属性注入注解,UserService中注入了UserDao
*/
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService UserService = (UserService)applicationContext.getBean("UserService");
UserService.save();
}
生命周期及作用范围的注解
@PostConstruct:初始化
@PreDestroy:销毁
@Scope:作用域
@Service("CustomerService")
@Scope("prototype")
public class CustomerService {
@PostConstruct
public void init(){
System.out.println("CustomerService被初始化了");
}
public void save(){
System.out.println("CustomerService的save方法执行了");
}
@PreDestroy
public void destory(){
System.out.println("CustomerService被销毁了");
}
}