目录
5.2.3、BeanFactory 和FactoryBean对比:
5.4.2、BeanPOSTProcessor后处理Bean
6、集合注入(Array、List、Set、Map、Properties)
1、Spring框架概述
2、IOC
2.1、导入jar包
四个核心(beans、core、context、expression)和一个依赖(commons.logging)
2.2、目标类
在之前的学习中,通常通过new实例化对象,学习spring框架后,将由spring创建对象的实例,即IoC(Inverse of control,控制反转)
创建UserService接口和其实现类
public interface UserService { public void addUser(); } public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO 自动生成的方法存根 System.out.println("test of ioc"); } }
2.3、配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here <bean>这个标签配置的是我们需要创建的对象 id:用于之后从Spring容器获得实例时使用 class:需要创建实例时的全限定名 --> <bean id="UserServiceId" class = "test_ioc.UserServiceImpl" ></bean> </beans>
2.4、测试
public class TestIoC { @Test public void demo01() { //之前学习的是以下方式new实例对象 UserService userService = new UserServiceImpl(); userService.addUser(); } @Test public void demo02() { /* * 从Spring容器中获得实例对象 * 1、获取容器 * 2、获得内容 */ //1、获取容器 String xmlPath = "applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //2、获取内容:不需要自己new 都是从spring容器中获得 UserService userService = (UserService) applicationContext.getBean("UserServiceId"); userService.addUser(); } }
结果如下:
3、DI
3.1、依赖注入
依赖:一个对象需要使用到另一个对象注入:通过setter方法进行另一个对象实例设置
class B{ private A a; setter方法; };//B中有一个成员变量a,称为B依赖于A
3.2、配置信息
<bean id = "" class = ""> <property name = "" ref = ""></property> </bean> <property>标签:用于进行属性注入 name :bean的属性名,通过setter方法获得 ref:另一个bean的id值的引用
3.3、举例说明
1、目标类:dao、service
- 创建BookService接口和实现类
- 创建BookDao接口和实现类
public interface BookDao { public void addBook(); } public class BookDaoImpl implements BookDao { @Override public void addBook() { // TODO 自动生成的方法存根 System.out.println("di add book"); } } public interface BookService { public void addBook(); } public class BookServiceImpl implements BookService { //方式一:接口+实现类 //private BookDao bookDao = new BookDaoImpl(); //方式二:接口+setter private BookDao bookDao; //setter方法 public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } @Override public void addBook() { // TODO 自动生成的方法存根 this.bookDao.addBook(); } }
2、配置文件
- 将dao和service配置到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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here 模拟spring的执行过程 创建service实例:BookService bookService = new BookServiceImpl(); IoC (<bean>) 创建dao实例:BookDao bookDao = new BookDaoImpl(); IoC (<bean>) 将dao设置给service:bookService.setBookDao(bookDao); DI (<property>) <property>标签:用于进行属性注入 name :bean的属性名,通过setter方法获得 bookDao ref:另一个bean的id值的引用 bookDaoId --> <!-- 创建service--> <bean id="bookServiceId" class="test_di.BookServiceImpl"> <property name="bookDao" ref="bookDaoId"></property> </bean> <!-- 创建dao--> <bean id="bookDaoId" class = "test_di.BookDaoImpl"></bean> </beans>
3、测试
public class TestDi { @Test public void demo() { //从spring容器中获得 String xmlPath = "test_di/applicationContext.xml"; ApplicationContext applicationcontext= new ClassPathXmlApplicationContext(xmlPath); BookService bookService = (BookService) applicationcontext.getBean("bookServiceId"); bookService.addBook(); } }
4、核心API 、
4.1、BeanFactory:
工厂,用于生成任意bean。采取延迟加载,第一次getBean时会初始化Bean
4.2、ApplicationContext:
是BeanFactory的子接口,功能更加强大(国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现)。当配置文件被加载就进行了对象的实例化
- ClassPathXmlApplicationContext:用于加载classpath(类路径,src)下的xml
- FileSystemXmlApplicationContext:用于加载指定盘符下的xml
5、装配Bean基于XML
5.1、实例化方式(三种)
5.1.1、默认构造
<bean id="" class=""></bean>; --->必须提供默认构造(就是没有写构造方法时系统默认的无参构造)
5.1.2、静态工厂及其测试:
- 常用于Spring整合其他框架(工具)
- 用于生产实例对象,所有的方法必须是static
配置信息
<bean id="" class="工厂的全限定类名" factory-method="静态方法"></bean>
测试
之前的学习的静态工厂:
//People接口 public interface People { public void newPeople(); } //People接口的实现类 public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自动生成的方法存根 System.out.println("create a people"); } } //静态工厂 public class MyBeanFactory { public static People createPeople() { return new PeopleImpl(); } } //静态工厂测试 public class TestStaticFactory { @Test public void demo01() { People people = MyBeanFactory.createPeople(); people.newPeople(); } }
学习Spring后:
//测试类如下 public class TestStaticFactory { @Test public void demo02() { //Spring工厂 String xmlPath = "test_b_inject_static_factory/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); } }
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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here--> <!-- 将静态工厂创建的实例教育spring class:确定静态工厂全限定名 factory-method:确定静态方法名 --> <bean id="People" class = "test_b_inject_static_factory.MyBeanFactory" factory-method="createPeople"></bean> </beans>
5.1.3、实例工厂及其测试
- 必须现有工厂的实例对象,然后通过实例对象去创建对象。
- 提供的所有方法是非静态的
配置信息
<bean id = "" factory-bean = "实例工厂" factory-method = "普通方法"></bean>
测试
之前的学习
//People类接口 public interface People { public void newPeople(); } //People类的实现类 public class PeopleImpl implements People{ @Override public void newPeople() { // TODO 自动生成的方法存根 System.out.println("create a people"); } } //实例工厂 public class MyBeanFactory { public People createPeople() { return new PeopleImpl(); } } //测试类 public class TestFactory { @Test public void demo01() { //1、创建工厂 MyBeanFactory myBeanFactory = new MyBeanFactory(); //2、通过工厂实例获取对象 People people = myBeanFactory.createPeople(); people.newPeople(); } }
学习spring后
public class TestFactory { @Test public void demo02() { String xmlPath = "test_c_inject_factory/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); } }
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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here--> <!-- 创建工厂实例 --> <bean id = "MyBeanFactory" class = "test_c_inject_factory.MyBeanFactory" ></bean> <!-- 获得People factory-bean:获得工厂实例 factory-method:确定普通方法的 --> <bean id = "People" factory-bean = "MyBeanFactory" factory-method="createPeople"></bean> </beans>
测试结果
5.2、Bean的种类
5.2.1、普通Bean:
之前的操作都是普通bean,<bean id="" class="A">,spring直接创建A的实例,并返回
5.2.2、FactoryBean:
是一个特殊的bean,具有工厂生成对象的能力,只能生成特定的对象。bean必须实现FactoryBean的接口,此接口提供一个方法getObject()用于获得特定的bean。-----<bean id="" class="FB">,先创建FB实例,然后调用getObject()方法,并返回方法的返回值
5.2.3、BeanFactory 和FactoryBean对比:
BeanFactory是工厂,用于生成任意Bean,FactoryBean是特殊的bean,用于生成另一个特定的bean。例如ProxyFactoryBean,此工厂bean用于生产代理,<bean id="" class="...ProxyFactoryBean">获得代理对象实例。AOP使用
5.3、作用域
5.3.1、作用域:
用于确定spring创建bean实例个数
类别 | 说明 |
singleton | 在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean() |
request | 每次HTTP请求都会创建一个新的Bean,仅适用于webApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于webApplicationContext环境 |
globalSession | 一般用于Portlet应用环境,该作用域仅适用于webApplicationContext环境 |
5.3.2、取值:
singleton:单例,默认情况下是单例模式
prototype:多例,每执行一次getBean()获得一次实例
5.3.3、配置信息:
<bean id="" class="" scope="取值"></bean> 单例模式: <bean id="People" class = "PeopleImpl"></bean> 多例模式: <bean id="People" class = "PeopleImpl" scope = "prototype"></bean>
5.3.4、测试
测试如下代码运行结果分别如下:
//People和PeopleImpl与上述相同 public class TestFactory { @Test public void demo01() { String xmlPath = "test_d_scope/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people1 = applicationContext.getBean("People",People.class); People people2 = applicationContext.getBean("People",People.class); System.out.println(people1); System.out.println(people2); } }
4、Bean的生命周期
5.4.1、初始化和销毁及其测试
- 目标方法执行前会执行初始化方法
- 执行销毁方法的两点要求:
- 容器必须close,才执行销毁方法
- 必须是单例模式(默认情况下就是单例模式)
<bean id = "" class = "" init-method = "初始化的方法名" destory-method = "销毁的方法名称"> init-method:用于配置初始化方法,准备数据 destroy-method:用于配置销毁方法,清理资源等
测试代码:在PeopleImpl类中添加初始化和销毁方法
public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自动生成的方法存根 System.out.println("create a people"); } //初始化方法 public void myInit() { System.out.println("my init method"); } //销毁方法 public void myDestroy() { System.out.println("my destroy method"); } }
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "People" class = "test_e_lifecycle.PeopleImpl" init-method = "myInit" destroy-method = "myDestroy"></bean> </beans>
测试类
public class TestFactory { @Test public void demo01() throws Exception, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { String xmlPath = "test_e_lifecycle/applicationContext.xml"; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("People",People.class); people.newPeople(); //要求1、容器必须close,销毁方法才执行 2、必须是单例模式 //applicationContext.getClass().getMethod("close").invoke(applicationContext); //此ApplicationContext接口中没有定义close()方法,但其实现类提供 applicationContext.close(); } }
测试结果:
5.4.2、BeanPOSTProcessor后处理Bean
- spring提供的一种机制,只要去实现此接口BeanPostProcessor,并将实现类提供给spring容器,spring容器将自动的执行,在初始化方法前执行before(),在初始化方法后执行after()
- Factory hook(钩子)that allows for custom modification of new instances,e.g.checking for marker interfaces or wrapping them with proxies.(spring提供的工厂钩子,用于修改实例对象,可以生成代理对象,是AOP的底层 )
- 模拟:
A a = new A(); a = B.before(a);//将a的实例对象传递给后处理bean,可以生成代理对象并返回 a.init();//此时a已经是代理对象 a = B.after(a); ----开启事务---- a.method();//生成代理对象,目的是:在目标方法执行前后执行(例如开启事务、提交事务) ----提交事务---- a.destory();
- 配置信息
<bean class=""></bean>
- 测试
- BeanPostProcessor实现类:此时返回值为null,则会出现空指针异常
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("before method"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("after method"); return bean; } }
- 配置文件:(5.4.1配置文件的基础上,将后处理的实现类注册给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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- bean definitions here init-method:用于配置初始化方法:准备数据 destroy-method:用于配置销毁方法:清理资源等 --> <bean id = "People" class = "test_e_lifecycle.PeopleImpl" init-method = "myInit" destroy-method = "myDestroy"></bean> <!-- 将后处理的实现类注册给spring--> <bean class = "test_e_lifecycle.MyBeanPostProcessor"></bean> </beans>
- 测试结果:在执行before()方法后,实例对象变为空,出现java.lang.NullPointerException
BeanPostProcessor的实现类中的方法添加返回值:
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("before method" + " , " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("after method" + " , " + beanName); return bean; } }
- 结果如下:此时就会按照:before()、init()、after()、实现类的方法、destroy()的顺序进行执行
- 继续实现在执行目标方法前后进行开启事务和提交事务,修改BeanPostProcessor的实现类
public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("before method" + " , " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO 自动生成的方法存根 System.out.println("after method" + " , " + beanName); //bean是目标对象 //生成jdk代理 return Proxy.newProxyInstance( MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO 自动生成的方法存根 System.out.println("-----开启事事务-----"); //执行目标方法 Object obj = method.invoke(bean, args); System.out.println("-----提交事务-----"); return obj; }}); } }
- 结果:
- 总结:两个步骤
- BeanPostProcessor的实现类 (涉及到动态代理)
- 配置 <bean class=“BeanPostProcessor的实现类”></bean>
5、属性依赖注入
5.5.1、构造方法(之后再补充)
5.5.2、setter方法
- 普通类型属性的配置文件
<bean id = "" class = "实现类的权限定名"> <!-- 第一种方式 (推荐)--> <property name = "属性名" value = "值"></property> <!-- 第二种方式 (不推荐)--> <property name = "属性名"> <value>"值"</value> </property> </bean>
- 引用类型属性的配置文件
<bean id = "" class = "实现类权限定名"> <!-- 第一种方法 (推荐)--> <property name = "属性名" ref = "另一个bean的id"></property> <!-- 第二种方法 (不推荐)--> <property name = "属性名"> <ref bean = "另一个bean的id"/> </property> </bean>
-
测试
准备的两个类:
public class People { private String pName; private Integer age; private Address homeAddr;//家庭地址 private Address companyAddr;//公司地址 public String getpName() { return pName; } public void setpName(String pName) { this.pName = pName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Address getHomeAddr() { return homeAddr; } public void setHomeAddr(Address homeAddr) { this.homeAddr = homeAddr; } public Address getCompanyAddr() { return companyAddr; } public void setCompanyAddr(Address companyAddr) { this.companyAddr = companyAddr; } @Override public String toString() { return "People [pName=" + pName + ", age=" + age + ", homeAddr=" + homeAddr + ", companyAddr=" + companyAddr+ "]"; } } /********************************************************************************/ public class Address { private String addr;//地址信息 private String tel;//地址的详细电话 //添加setter方法 public void setAddr(String addr) { this.addr = addr; } public void setTel(String tel) { this.tel = tel; } public String getAddr() { return addr; } public String getTel() { return tel; } @Override public String toString() { return "Address [addr=" + addr + ", tel=" + tel + "]"; } }
编写配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "People" class = "test_f_xml_b_setter.People"> <property name="pName" value = "jack"></property> <property name="age"> <value>20</value> </property> <property name="homeAddr" ref = "homeAddr"></property> <property name = "companyAddr"> <ref bean = "companyAddr"/> </property> </bean> <!-- Address --> <bean id="homeAddr" class = "test_f_xml_b_setter.Address"> <property name = "addr" value = "东风大道"></property> <property name = "tel" value = "88888888"></property> </bean> <bean id="companyAddr" class = "test_f_xml_b_setter.Address"> <property name ="addr" value = "发展大道"></property> <property name ="tel" value = "66666666"></property> </bean> </beans>
测试类
public class TestSetter { @Test public void demo01() { String xmlPath = "test_f_xml_b_setter/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = (People) applicationContext.getBean("People"); String str = people.toString(); System.out.println(str); } }
测试结果:
5.5.3、P命令空间[了解]
- 作用:对“setter方法”注入进行简化,替换<property>,替换如下
<bean id = "" class = "实现类的权限定名" p:属性名 = "普通值" p:属性名-ref = "引用值">
- p命名空间使用的前提,必须添加命名空间
- 测试
修改配置文件如下:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "homeAddr" class = "test_f_xml_c_p.Address" p:addr="东风大道" p:tel="88888888"> </bean> <bean id = "companyAddr" class = "test_f_xml_c_p.Address" p:addr="发展大道" p:tel="66666666"> </bean> <bean id = "People" class = "test_f_xml_c_p.People" p:pName = "jack" p:age = "20" p:homeAddr-ref="homeAddr" p:companyAddr-ref = "companyAddr"> </bean> </beans>
测试结果与5.5.3相同
5.5.4、SpEL(了解)
- 对<property>进行统一编程,所有的内容都使用value
<property name="" value="#(表达式)"></property> 数字:#{123} 字符串:#{'jack'} 另外一个bean的引用:#{beanId} 操作数据:#{beanId.propName} 执行方法:#{beadId.toString()} 静态方法或字段:#{T(类的权限定名).字段|方法}
- 测试
public class Customer { private String cname; private Integer age; private Double pi;//Math.pi public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public Double getPi() { return pi; } public void setPi(Double pi) { this.pi = pi; } @Override public String toString() { return "Customer [cname=" + cname + ", age=" + age + ", pi=" + pi + "]"; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "customer" class = "test_f_xml_d_spel.Customer"> <property name = "cname" value = "#{'jack'}"></property> <property name = "age" value = "#{24}"></property> <property name ="pi" value = "#{T(java.lang.Math).PI}"></property> </bean> </beans>
测试类:
public class TestSpel { @Test public void demo01() { String xmlPath = "test_f_xml_d_spel/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); Customer customer = applicationContext.getBean("customer",Customer.class); System.out.println(customer.toString()); } }
测试结果
6、集合注入(Array、List、Set、Map、Properties)
- 集合的注入都是给<property>添加子标签
- 一般情况下普通数据是<value>,引用数据是<ref>
- 数组:<array>
- List:<list>
- Set:<set>
- Map:<map>
- Properties:<props>
测试
public class CollectionData { private String[] arrayData; private List<String> listData; private Set<String> setData; private Map<String,String> mapData; private Properties propsData; public String[] getArrayData() { return arrayData; } public void setArrayData(String[] arrayData) { this.arrayData = arrayData; } public List<String> getListData() { return listData; } public void setListData(List<String> listData) { this.listData = listData; } public Set<String> getSetData() { return setData; } public void setSetData(Set<String> setData) { this.setData = setData; } public Map<String, String> getMapData() { return mapData; } public void setMapData(Map<String, String> mapData) { this.mapData = mapData; } public Properties getPropsData() { return propsData; } public void setPropsData(Properties propsData) { this.propsData = propsData; } @Override public String toString() { return "CollectionData [\narrayData=" + Arrays.toString(arrayData) + ", \nlistData=" + listData + ", \nsetData=" + setData + ", \nmapData=" + mapData + ", \npropsData=" + propsData + "\n]"; } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "collectionData" class = "test_f_xml_e_collection.CollectionData"> <property name = "arrayData"> <array> <value>array-String1</value> <value>array-String2</value> <value>array-String3</value> <value>array-String4</value> </array> </property> <property name = "listData"> <list> <value>list-String1</value> <value>list-String2</value> <value>list-String3</value> <value>list-String4</value> </list> </property> <property name = "SetData"> <set> <value>set-String1</value> <value>set-String2</value> <value>set-String3</value> </set> </property> <property name="mapData"> <map> <entry key="key1" value="map-String1"></entry> <entry key="key2" value="map-String2"></entry> <entry key="key3" value="map-String3"></entry> <entry> <key><value>key4</value></key> <value>map-String4</value> </entry> </map> </property> <property name="propsData"> <props> <prop key="key1">props-String1</prop> <prop key="key2">props-String2</prop> <prop key="key3">props-String3</prop> </props> </property> </bean> </beans>
测试类:
public class TestCollection { @Test public void demo() { String xmlPath = "test_f_xml_e_collection/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); CollectionData collectionData = applicationContext.getBean("collectionData",CollectionData.class); System.out.println(collectionData.toString()); } }
测试结果:
6、装配Bean基于注解
6.1、什么是注解
- 注解:就是一个类,使用@注解名称
- 开发中:使用注解取代xml文件
- 使用的前提:添加命名空间,让spring扫描含有注解的类
- 在参考文件中找到:the context schema
- schema的命名空间
1、命名空间声明:
默认:xmlns=”“ <标签名>--> <bean>
显示:xmlns别名=”“ <别名标签名>--><context:...>
2、确定schema xsd文件位置
xsl:schemaLocation=”名称1 位置1 名称2 位置2....“(内容都是成对的,【名称 位置】)
6.2、注解分类
1、@Component 取代 <bean class = “”>
@Component("id) 取代 <bean id = "" class = "">
测试:
//定义一个接口 public interface People { public void newPeople(); } //接口的实现类 @Component("people") public class PeopleImpl implements People { @Override public void newPeople() { // TODO 自动生成的方法存根 System.out.println("create a people"); } } //测试类 public class TestDemo { @Test public void demo() { String xmlPath = "test_g_annotation_a_ioc/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); People people = applicationContext.getBean("people",People.class); people.newPeople(); } }
配置文件:
<?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 base-package="test_g_annotation_a_ioc"></context:component-scan> </beans>
2、web开发,提供3个@Component注解衍生注解(功能一样),取代<bean class="">
@Repository:dao层
@Service:service层
@Controller:web层
3、依赖注入 给私有字段设置,也可以给setter方法设置
普通值:@value("")
引用值:
方式一:按照【类型】注入
@Autowired
方式二:按照【名称】注入1
@Autowired
@Qualifier("名称")
方式三:按照【名称】注入2
@Resource("名称")
测试:
@Controller("studentActionId") public class StudentAction { @Autowired//默认 按照类型注入 private StudentService studentService; public void execute() { studentService.addStudent(); } } //service public interface StudentService { public void addStudent(); } //StudentService的实现类 @Service public class StudentServiceImpl implements StudentService { private StudentDao studentDao; @Autowired//默认 按照类型注入 @Qualifier("studentDaoId") public void setStudentDao(StudentDao studentDao) { this.studentDao = studentDao; } @Override public void addStudent() { // TODO 自动生成的方法存根 //System.out.println("service"); studentDao.addStudent(); } } //dao public interface StudentDao { public void addStudent(); } //StudentDao的实现类 @Repository("studentDaoId") public class StudentDaoImpl implements StudentDao { @Override public void addStudent() { // TODO 自动生成的方法存根 System.out.println("create a student"); } }
测试类:
public class TestDemo { @Test public void demo() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test_g_annotation_b_web/applicationContext.xml"); StudentAction studentAction = (StudentAction) applicationContext.getBean("studentActionId"); studentAction.execute(); } }
配置文件
<?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 base-package="test_g_annotation_b_web"></context:component-scan> </beans>
6.3、生命周期
初始化:@PostConstruct
销毁:@PreDestory
6.4、作用域
@Scope("prototype") 多例
7、注解和xml混合使用
1、将所有的bean都配置在xml中 <bean id = “” class = “”>
2、将所有的依赖都使用注解 @Autowired
默认不生效,为了生效,需要在xml文件中配置:<context annotation-config></context annotation-config>
总结:注解1 :<context-component-scan base-package ="">
注解2 :<context annotation-config>
1、一般两个注解不一起使用
1、"注解1"扫描含有注解(@Component等)类的,注入的注解自动的生效,"注解2"只在xml和注解(注入)混合使用时,使注入注解生效