- 框架
- 使用框架步骤
- spring
- 单例设计模式:
- spring创建对象的是单例还是多例
- spring容器的生命周期:容器何时创建,何时销毁
- spring DI dependency injection依赖注入:
- spring是如何处理继承:
- 自动装配
- 注解
框架
spring mvc框架
servlet:只做三件事
- 1.获取数据 n多个request.getParameter(“key”);
- 2.调用业务
- 3.根据业务结果做相应的跳转(重定向和转发) 根据业务的结果相应json数据到js客户端 spring mvc:
- 1.获取数据 恭喜你,springmvc 帮你做了
- 2.调用业务 程序员专注于做相应的业务
- 3.根据业务结果做相应的跳转(重定向和转发) 恭喜你,springmvc 帮你做了
mybatis框架
- 原生jdbc 开发效率低,执行效率高 手洗衣服
- 基于原生jdbc衍生出CommonDao 开发效率稍高 手工搓衣板
- springjdbc是spring框架的产品 相同 品牌搓衣板
- mybatis框架 开发效率继续提高 半自动洗衣机
- hibernate框架 开发效率最高 全自动洗衣机
spring框架
原先对象的创建都是有程序员根据业务的需求来new对象,而且需要程序员管理对象之间的关系
用spring框架不但能帮程序员创建对象,而且还能管理对象之间的关系
对象之间的关系:依赖关系,组合关系(has a),继承关系(is a)
比如:
在UserServiceImpl类中需要UserDaoImpl的对象
UserServiceImpl依赖于UserDaoImpl
UserServiceImpl有一个UserDaoImpl
总结:框架就是用来提高开发效率,是程序员福音
spring框架: spring是一个开源的轻量级的应用开发框架,其目的用于企业级应用程序的开发,减少侵入(降低耦合)
解释几个必要的名词:
- 开源:开放源代码,提供框架源代码
- 轻量级:互相依赖越少,越轻量级
- 减少侵入/降低耦合:高内聚,低耦合
- 耦合的分类:
1.无/零耦合:类和类之间没有任何关系
2.抽象耦合:在本类中耦合的是另一个类的抽象(接口(推荐),抽象类(不推荐)
面向接口编程,面向抽象编程
//UserDao是UserDaoImpl的接口
//UserDao是UserDao_OracleImpl的接口
比如:public class UserServiceImpl{
private UserDao userDao;//还没有new,等下面返回一个userDao对象
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public Boolean addUser(){
userDao.addUser();
}
}
- 3.具体耦合:在本类中耦合的是另一个具体的类
比如:public class UserServiceImpl{
//UserDao是UserDaoImpl的接口
private UserDaoImpl userDao;
public Boolean addUser(){
userDao.addUser();
}
}
public class UserServiceImpl{
//UserDao是UserDaoImpl的接口
private UserDao userDao=new UserDaoImpl();//直接new出对象
public Boolean addUser(){
userDao.addUser();
}
}
使用框架步骤
spring有很多内容,现阶段只涉猎:
- spring IOC 控制反转
- spring DI 依赖注入
- spring aop 面向切面编程
- spring jdbc 品牌搓衣板
- spring 声明式事务管理
-
spring IOC 控制反转 Inversion of Control(IOC),把new对象不放在具体类中new,把new对象的控制权反转到第三方spring容器中 去new对象
-
spring DI 依赖注入 Dependency Injection(DI),就是把spring容器中new
1.导入jar包
- 方式一:
手动拷贝jar到项目中,然后右键单击jar包–build jar
spring-context.jar
spring-aop.jar
spring-beans.jar
spring-core.jar
spring-expression.jar - 方式二: 用maven下载jar包
<!-- spring context依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
2.创建清单文件:超级建议从开发文档中拷贝
原始清单文件:
<?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="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
修改清单文件:
<?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">
<!-- spring的清单文件,告知spirng容器要把谁实例化对象 -->
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
</beans>
3.初始化spring容器
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
从spring容器中取出对象
Hello hello=context.getBean("hello",Hello.class);
ioc容器实例化对象的若干常见错误:
有异常一定要先仔细阅读异常信息,针对eclipse mars2,及以前版本
如果有Caused by字样的异常信息,看最后的Caused by提示的信息
- Caused by: java.lang.ClassNotFoundException: com.tarena.ioc.Hello1
类没有发现异常,说明指定的类不存在
建议: 按住ctrl键 ,把鼠标放在class属性所对对应的类上,如果出现下划线,说明类写对了 - id的名称必须唯一的
<bean id="hello" class=""/>
Bean name ‘hello’ is already used in this
- 还有另一个中写法但不建议
<bean name="hello" class="" />
原因是name中不能写一些特殊字符
- 指定的清单文件不存在
不是运行的是src/java/resoureces/applicationContext.xml
实际运行的是类路径中的applicationContext.xml
Caused by: java.io.FileNotFoundException:
class path resource [applicationContext1.xml]
cannot be opened because it does not exist - 容器中没有取出对象 No bean named ‘hello2’ available
spring
spring的原理:
启动spring容器:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
- a.spring一定要正确加载和解析spring.xml文件
- b.把applicationContext.xml中的bean节点的内容解析出来并存储给map集合
- c.循环遍历map集合中的所有数据取出class属性对应的数据值,通过反射实例化对象
- Object obj=Class.forName(“包名.类名”).newInstance();//实例化的是无参数构造
- d.把创建完的对象存储到另一个map集合中,用bean的id作为key,new完的对象做为值,所谓spring容器就是一个map集合
- e.如果有属性需要注入,spring框架就帮你注入数据
getBean api方法:
- getBean(Class);//根据类型获取,必须容器中类型对象唯一
- getBean(String);//根据id从容器中获取对象,需要强制转换
- getBean(String,Class);//根据id和类型同时确定一个容器中的一个对象
spring的配置/清单文件不智能提示(不能联网时):
要求D:/beans/spring-beans-4.3.xsd,文件真实存在
<?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
file:///D:/beans/spring-beans-4.3.xsd">
<!-- spring的清单文件,告知spirng容器要把谁实例化对象 -->
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
<bean id="hello1" class="com.tarena.ioc.Hello"></bean>
</beans>
spring容器:
- 同一个类类型,可以实例化多次,但id的名称不能重复
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
<bean id="hello1" class="com.tarena.ioc.Hello"></bean>
- 一个类的对象被spring容器实例化,可以通过getBean方法可以取多次
spring容器实例化和管理对象的四种方式:
- 通过无参数构造方式实例化对象(推荐,重要,用的最多)
注意:此种情况是spring帮你创建对象,并把对象放在spring容器中管理
重要的前提,类中必须有一个无参数的构造
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
Caused by: java.lang.NoSuchMethodException: com.tarena.ioc.Hello.
- 静态工厂: 注意:此种情况不是spring帮你创建对象,是别的渠道创建的对象,交给spring管理
<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">
<!-- spring的清单文件,告知spirng容器要把谁实例化对象 -->
<!-- 静态工厂
所谓的静态工厂,通过类的名字调用类中一个静态方法,
由静态方法生产一个对象,交给spring容器来管理
class属性的值,是一个抽象类或普通类
factory-method是抽象类中的一个静态方法
-->
<bean id="calc"
class="java.util.Calendar"
factory-method="getInstance"></bean>
</beans>
- 实例工厂 注意:此种情况不是spring帮你创建对象,是别的渠道创建的对象,交给spring管理
<!-- 实例工厂
所谓的实例工厂,是区分生产对象的方法不是静态方法
先创建实例工厂对象if
通过factory-bean和factory-method来调用非静态方法,以获得Hello的对象,并交给spring管理
有两个对象
-->
<bean id="if" class="com.tarena.factory.InstanceFactory" ></bean>
<bean id="hello1"
factory-bean="if"
factory-method="getObject"></bean>
public class InstanceFactory {
public Hello getObject(){
return new Hello();
}
}
- spring工厂 注意:此种情况不是spring帮你创建对象,是别的渠道创建的对象,交给spring管理
<!-- spring工厂
本应该实例化SpringFactory对象,但这个类实现了FactoryBean接口
spring会自动调用getObject方法,方法返回的对象就是要交个spring管理的对象
-->
<bean id="hello2" class="cn.tedu.factory.SpringFactory"></bean>
public class SpringFactory implements FactoryBean<Hello>{
@Override
public Hello getObject() throws Exception {
// TODO Auto-generated method stub
return new Hello();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Hello.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
}
结论:spring想要达到,用纯java能创建的对象,spring框架也可以创建和管理这些对象
单例设计模式:
就是对象在内存中永远只有一个对象
要求能独立手写出三个以上的单例写法
/**
* 懒汉式,线程不安全
* @author Administrator
*
*/
public class Singleton1 {
private static Singleton1 instance;
private Singleton1(){
}
public static Singleton1 getInstance(){
if(instance==null){
instance=new Singleton1();
}
return instance;
}
}
/**
* 懒汉式,线程安全
* @author Administrator
*
*/
public class Singleton2 {
private static Singleton2 instance;
private Singleton2(){
}
public static synchronized Singleton2 getInstance(){
if(instance==null){
instance=new Singleton2();
}
return instance;
}
}
/**
* 饿汉式,线程不安全
* @author Administrator
*
*/
public class Singleton3 {
private static Singleton3 instance=new Singleton3();
private Singleton3(){
}
public static Singleton3 getInstance(){
return instance;
}
}
/**
* 饿汉式,变种
* @author Administrator
*
*/
public class Singleton4 {
private static Singleton4 instance=null;
static{
instance=new Singleton4();
}
private Singleton4(){
}
public static Singleton4 getInstance(){
return instance;
}
}
spring创建对象的是单例还是多例
- spring容器默认情况下,创建的对象是单例的 说明对象在容器中只有一个,可以从容器中取多次,对象的生命周期,跟容器的生命周期相同
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
<!--等同于-->
<bean id="hello" class="com.tarena.ioc.Hello" scope="singleton"></bean>
- spring的多例 scope=”prototype”
什么时候getBean,什么时候才实例化对象,并把对象返回给用户,对象的生命周期不是由spring容器掌控,由用户来掌控
注意,在spring容器初始化的时候是不实例化对象的
<bean id="hello" class="com.tarena.ioc.Hello" scope="prototype"></bean>
spring容器的生命周期:容器何时创建,何时销毁
何时创建:生命周期开始,之后自动调用init方法
AbstractApplicationContext context =
new ClassPathXmlApplicationContext("xxx.xml");
- a.局部初始化 init是一个方法名称
<bean id="hello" class="com.tarena.ioc.Hello" init-method="init"></bean>
- b.全局初始化
<beans default-init-method="init"><beans>
何时销毁:生命周期结束,自动调用destroy方法context.close();
- a.局部销毁 destroy是一个方法名称
<bean id="hello" class="com.tarena.ioc.Hello" destroy-method="destroy"></bean>
- b.全局销毁
<beans default-destroy-method="destroy"><beans>
spring容器中的对象懒加载:
就是控制对象创建时机
<bean id="hello"
class="com.tarena.ioc.Hello"
scope="singleton"
lazy-init="true"></bean>
虽然scop=”singleton”,但是如果懒加载为true,就是不在容器初始化的时候创建对象,而是在getBean的时候才创建对象,对象还是只有一个以后再getBean,始终是获取第一个次getBean时创建的对象
全局写法
<beans default-lazy-init="true"></beans>
指定beans中的所有的bean都懒加载
在spring的配置文件中导入其他的spring的配置文件
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
</beans>
spring DI dependency injection依赖注入:
注入的方式:
- setter方式注入
- 构造函数注入
setter方式注入分类:
对象注入,单值注入,集合注入,表达式注入,空值注入
对象注入:
<?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="userDao"
class="com.tarena.dao.impl.UserDaoImpl"></bean>
<!--
<bean节点用来告知spring实例化或管理对象
<property节点 是用告知spring有对象的注入,相当于告知spring要管理对象的关系
name属性 其实对应的是 <bean class属性对应类中的setter方法
name="userDao" userDao->setUserDao
把name属性的值的第一个字母大写,前面加上set,构建一个字符串setUserDao
拿这个setUserDao字符串取UserServiceImpl类中寻找是否有此名称的方法
如果有set方法,就反射调用这个set方法
ref="userDao" ref :reference 引用 要引用一个对象userDao
注意,ref引用的对象,一定是引自spring容器 userDao是容器中的一个唯一的id
-->
<bean id="userService" class="com.tarena.service.impl.UserServiceImpl">
<!-- 对象注入 -->
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
值注入:
<?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节点告知spring实例化管理对象
property节点,告知spring做数据注入
name="age" age->setAge
name="address" address->setAddress
在ValueInject类中应该有两个set方法分别是setAge方法和setAddress方法
value="18" ,双引号是数据的内容只是分隔符
value所对应的数据就是单值,注意不是从容器取的数据,只是一个固定值而已
-->
<bean id="valueInject"
class="com.tarena.value.ValueInject">
<property name="age" value="18"></property>
<property name="address" value="北京海淀巨山农场"></property>
</bean>
</beans>
集合注入:(直接集合注入,间接集合注入)
- 直接集合注入: 特点:只能使用一次
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
<bean id="msg" class="com.tarena.collection.Message">
<property name="list">
<list>
<value>北京</value>
<value>上海</value>
<value>广州</value>
<ref bean="hello"/>
</list>
</property>
<property name="set">
<set>
<value>北京</value>
<value>上海</value>
<value>广州</value>
<ref bean="hello"/>
</set>
</property>
<property name="map">
<map>
<entry key="bj" value="北京"></entry>
<entry key="sh" value="上海"></entry>
<entry key="gz" value="广州"></entry>
<entry key="h" value-ref="hello"></entry>
</map>
</property>
<property name="props">
<props>
<prop key="bj">北京</prop>
<prop key="sh">上海</prop>
<prop key="gz">广州</prop>
</props>
</property>
</bean>
</beans>
- 间接集合注入: 特点:可以使用多次
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="hello" class="com.tarena.ioc.Hello"></bean>
<!-- 间接集合注入 -->
<util:list id="uList">
<value>北京</value>
<value>上海</value>
<value>广州</value>
<ref bean="hello"/>
</util:list>
<util:set id="uSet">
<value>北京</value>
<value>上海</value>
<value>广州</value>
<ref bean="hello"/>
</util:set>
<util:map id="uMap">
<entry key="bj" value="北京"></entry>
<entry key="sh" value="上海"></entry>
<entry key="gz" value="广州"></entry>
<entry key="h" value-ref="hello"></entry>
</util:map>
<util:properties id="uProps">
<prop key="bj">北京</prop>
<prop key="sh">上海</prop>
<prop key="gz">广州</prop>
</util:properties>
<bean id="msg1" class="com.tarena.collection.Message">
<property name="list" ref="uList"></property>
<property name="set" ref="uSet"></property>
<property name="map" ref="uMap"></property>
<property name="props" ref="uProps"></property>
</bean>
</beans>
表达式注入:
前提:必须有属性文件,表达式注入就是把属性文件的数据,通过spring注入给某个对象中表达式注入一定跟属性文件有关
mysql.properties
jdbc_driverClass=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/tesdb
jdbc_userName=root
jdbc_userPassword=root
public class JdbcUtil {
private String driverClass;
private String url;
private String username;
private String userpassword;
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
@Override
public String toString() {
return "JdbcUtil [driverClass=" + driverClass + ", url=" + url + ", username=" + username + ", userpassword="
+ userpassword + "]";
}
}
${}方式:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 用spring加载指定的属性文件 ,多个文件用逗号间隔-->
<context:property-placeholder location="classpath:conf/mysql.properties,classpath:conf/page.properties"/>
<bean id="jdbcUtil" class="com.tarena.expression.JdbcUtil">
<property name="driverClass" value="${jdbc_driverClass}"></property>
<property name="url" value="${jdbc_url}"></property>
<property name="username" value="${jdbc_userName}"></property>
<property name="userpassword" value="${jdbc_userPassword}"></property>
</bean>
<bean id="pageUtil" class="com.tarena.expression.PageUtil">
<property name="pageSize" value="${pageSize}"></property>
<property name="showNum_a" value="${showNum_a}"></property>
</bean>
</beans>
#{}方式:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 用spring加载指定的属性文件 ,多个文件用逗号间隔-->
<util:properties id="manyProperty"
location="classpath:conf/mysql.properties,classpath:conf/page.properties"></util:properties>
<bean id="jdbcUtil" class="com.tarena.expression.JdbcUtil">
<property name="driverClass" value="#{manyProperty.jdbc_driverClass}"></property>
<property name="url" value="#{manyProperty.jdbc_url}"></property>
<property name="username" value="#{manyProperty.jdbc_userName}"></property>
<property name="userpassword" value="#{manyProperty.jdbc_userPassword}"></property>
</bean>
<bean id="pageUtil" class="com.tarena.expression.PageUtil">
<property name="pageSize" value="#{manyProperty.pageSize}"></property>
<property name="showNum_a" value="#{manyProperty.showNum_a}"></property>
</bean>
</beans>
空值注入:
public class Kong {
private String str1;
private String str2;
public void setStr1(String str1) {
this.str1 = str1;
}
public void setStr2(String str2) {
this.str2 = str2;
}
@Override
public String toString() {
return "Kong [str1=" + str1 + ", str2=" + str2 + "]";
}
}
<bean id="kong" class="com.tarena.kong.Kong">
<property name="str1" value=""></property>
<property name="str2">
<null></null>
</property>
</bean>
构造函数注入数据
- 实例化对象
- 注入数据
public class ConstructorDI {
private int age;
private UserDao userDao;
private String name;
public ConstructorDI(int age,UserDao userDao,String name){
this.age=age;
this.userDao=userDao;
this.name=name;
}
@Override
public String toString() {
return "ConstructorDI [age=" + age + ", userDao=" + userDao + ", name=" + name + "]";
}
}
<bean id="userDao" class="com.tarena.dao.impl.UserDaoImpl"></bean>
<bean id="constructor" class="com.tarena.constructor.ConstructorDI">
<constructor-arg index="0" value="18"></constructor-arg>
<constructor-arg index="1" ref="userDao"></constructor-arg>
<constructor-arg index="2" value="zhangsan"></constructor-arg>
</bean>
对象注入和单值注入的另一种新写法
<!-- 新写法 spring新的推荐写法
如果没有ref 就是老写法的value
有ref 就是引用容器的某个对象
p:的值就是老写法的name
-->
<bean id="setterNew1"
class="com.tarena.setternew.SetterNew"
p:name="张三"
p:age="18"
p:hello-ref="hello"
p:userDao-ref="userDao">
</bean>
开发中用setter方式居多,构造函数注入方式少
在框架的源码中构造居多,setter方式也有
spring是如何处理继承:
spring中的继承需要注意问题:
- 对象都要交给spring实例化
- 对象的关系也要交给spring来管理
- 父类的对象是spring创建,而不是由原生java自动创建的
- 在子类对象中用parent属性指定spring容器中的父类对象
- 如果父类是抽象,要添加一个abstract=true
<!-- 实例化DataSource对象 -->
<bean id="dataSource" class="com.tarena.jicheng.DataSource">
<property name="url" value="jdbc:mysql://localhost:3306/testdb"></property>
</bean>
<!-- 实例化BaseDao对象 -->
<bean id="baseDao"
class="com.tarena.jicheng.BaseDao"
abstract="true">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 实例化UserDao对象 -->
<bean id="uDao"
class="com.tarena.jicheng.UserDao"
parent="baseDao">
</bean>
public class DataSource {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
public abstract class BaseDao {
private DataSource dataSource;
public BaseDao(){
System.out.println("BaseDao.constructor()");
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
public class UserDao extends BaseDao {
public UserDao(){
System.out.println("UserDao.constructor()");
}
public int addUser(){
System.out.println("addUser()");
DataSource ds=super.getDataSource();
System.out.println(ds.getUrl());
return 0;
}
}
@Test
public void testMethod3(){
//经过spring管理
ApplicationContext context=
new ClassPathXmlApplicationContext("spring_jicheng.xml");
UserDao uDao=context.getBean("uDao",UserDao.class);
uDao.addUser();
}
自动装配
在spring中能够提高开发效率那几种做法(不推荐:原因是降低代码的可读性) 所谓的spring的自动装配/自动注入
<!-- spring中有关提高开发效率的做法 -->
<!--
autowire:自动装配
autowire="byName" 按照名称装配
首先反射com.tarena.wire.User类中的所有方法,
找出所有的setter方法,把set去掉,把剩下的字符串的第一个字母小写
拿剩下字符串作为id去spring容器中寻找对应的对象,如果找到就反射
调用setter方法,注入对象 -->
<bean id="user1"
class="com.tarena.wire.User"
autowire="byName">
</bean>
<!--
autowire:byType
按类型装配,同样的类型在spring容器不能有第二个
-->
<bean id="user2"
class="com.tarena.wire.User"
autowire="byType">
</bean>
注解
DI的注解
用spring中某些注解替换配置文件中的property节点
- 用@Resource注解替换property节点 此注解是java的注解
- 用@Autowired注解替换property节点 是spring框架的注解
- 用@Inject注解替换property节点(不推荐使用)
- 用@Value注解替换property节点(只能操作属性文件)
前提:
需要注册一批java类来解析上面的注解
<context:annotation-config></context:annotation-config>
方式一: 用@Resource注解替换property节点
此注解是java的注解,隶属于javaEE规范
- 按照名称在spring容器中精确查找 name=”userDao” 拿userDao作为id去spring容器中寻找
public class UserServiceImpl{
@Resource(name="userDao")
private UserDao userDao;
}
- 按照属性名称userDao寻找 属性名称是userDao,拿userDao作为id去spring容器中寻找
public class UserServiceImpl{
@Resource
private UserDao userDao;
}
- 按照类型UserDao寻找 按照userDao11这个id去spring容器寻找,如果没有就按照类型UserDao去寻找,如果有就注入(UserDao的类型不能有第二个),如果没有就无法注入,报异常
public class UserServiceImpl{
@Resource
private UserDao userDao11;
}
总结:
- 如果按照1方式就直接查找,找到注入,找不到报异常
- 如果按照2方式就先按属性名称查找,找到注入
- 找不到就按照3方式 按类型注入,找到注入 找不到报异常
@Resource注解即可以写在属性上(用反射暴力注入)
@Resource也可以写在方法上(用反射非暴力注入)
方式二: 用@Autowired注解替换property节点
@Autowired注解默认是按照类型注入/装配 1.默认按照类型装配/注入,在容器中不能第二个相同的类型 public class UserServiceImpl{ @Autowired private UserDao userDao; } public class UserServiceImpl{ //false:对象可以为null ,true:属性必须存储对象,不能为null @Autowired(required=false) private UserDao userDao; } 2.也可以按照名称注入/装配 @Autowired @Qualifier public class UserServiceImpl{ @Autowired @Qualifier(value=”userDao”) private UserDao userDao; }
方式四:用@Value注解替换property节点(只能操作属性文件)
mysql.properties
jdbc_driverClass=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/tesdb
jdbc_userName=root
jdbc_userPassword=root
1.@Value(“${属性的key}”)
public class JdbcUtil1 {
@Value("${jdbc_driverClass}")
private String driverClass;
@Value("${jdbc_url}")
private String url;
@Value("${jdbc_userName}")
private String userName;
@Value("${jdbc_userPassword}")
private String userPassword;
@Override
public String toString() {
return "JdbcUtil1 [driverClass=" + driverClass + ", url=" + url + ", userName=" + userName + ", userPassword="
+ userPassword + "]";
}
}
spring的清单文件:
<!-- 用spring加载属性文件 多个文件用逗号间隔-->
<context:property-placeholder location="classpath:conf/mysql.properties,classpath:conf/page.properties"/>
<!-- 此节点注册了一批java类,这些java类用于解析下列注解
@Resource
@Autowired@Qualifer
@Value
-->
<context:annotation-config></context:annotation-config>
<bean id="jdbcUtil1" class="com.tarena.util.JdbcUtil1">
</bean>
2.@Value(“#{id.属性的key}”)
public class JdbcUtil2 {
@Value("#{manyProperty.jdbc_driverClass}")
private String driverClass;
@Value("#{manyProperty.jdbc_url}")
private String url;
@Value("#{manyProperty.jdbc_userName}")
private String userName;
@Value("#{manyProperty.jdbc_userPassword}")
private String userPassword;
@Override
public String toString() {
return "JdbcUtil1 [driverClass=" + driverClass + ", url=" + url + ", userName=" + userName + ", userPassword="
+ userPassword + "]";
}
}
spring的清单文件:
<!-- 用spring加载属性文件 多个文件用逗号间隔-->
<util:properties id="manyProperty"
location="classpath:conf/mysql.properties,classpath:conf/page.properties"></util:properties>
<!-- 此节点注册了一批java类,这些java类用于解析下列注解
@Resource
@Autowired@Qualifer
@Value
-->
<context:annotation-config></context:annotation-config>
<bean id="jdbcUtil2" class="com.tarena.util.JdbcUtil2">
</bean>
IOC的注解
用spirng中某些注解替换配置文件中的bean节点
- 用@Controller注解替换bean节点 应用控制器类上
- 用@Service注解替换bean节点 应用在业务类上
- 用@Repository注解替换bean节点 应用在dao类上
- 用@Component注解替换bean节点 应用在无法归属类别的类上
以上注解用法基本相同,就以@Service注解为例:
- 上面的4个注解只能修饰在类上
- @Service 修饰在哪个类上,spring就实例化这个类的对象,并放在容器中管理,对象的名字,也是容器中对象的id的命名规则把类的名字第一个字母小写后的字符串做为id的值
- @Service(value=”名字”) 修饰在类上,value=是可以省略,spring实例化对象,并放在spring容器中,”名字”作为对象的id
- spring必须注册一批java类,用于解析上面的4个注解
注册注解的解析类
<context:component-scan base-package="包名"></context:component-scan>
上下文的组件扫描 ,扫描的是包中的类
base-package属性指定的是包名,多个包名之间用逗号间隔
如果添加了这个组件扫描,就不需要添加
<context:annotation-config></context:annotation-config>
因为在注册组件扫描时,一并把
<context:annotation-config></context:annotation-config>
加载
补充几个常见的注解:
- @Scope(value=”prototype”) 多例 修饰在类上 @Scope(value=”singleton”) 单例 默认 修饰在类上
-
@Lazy(value=true false) //懒加载 修饰在类上 - @PostConstruct //表示初始化 修饰在方法上
- @PreDestroy //表示销毁 修饰在方法上