目录
3.scope="singleton"和 scope="prototype" 导致bean的创建时期不同
spring概述
1.什么是spring?
Spring是分层的JavaSE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核。
提供了展现层spring-mvc和持久层spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE企业应用开源框架
2.spring的优势
2.1方便解耦,简化开发
通过spring提供的IOC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以专注于上层的应用。
2.2AOP编程的支持
通过spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
2.3声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明方式灵活的进行事务管理,提高开发效率和质量
2.4方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的造作,而是随手可做的事项。
2.5方便集成各种优秀的框架
spring对各种优秀框架(Struts、Hibemate、Hessian、Quartz等)的支持
2.6降低JavaEE API的使用难度
spring对JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层、使这些API的使用难度大为降低
2.7Java源码时经典学习范例
spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣,它的源代码无疑是Java技术的最佳实践的范例。
3.spring的体系结构
spring配置文件
1.Bean标签基本配置(默认是无参构造创建)
作用:配置对象交由spring来创建
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
基本属性:
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称
当手动为实现类对象创建有参构造时(编译器默认的无参构造被取代)
出现错误
此时再手动在该类下创建无参构造
public AImpl(){}
配置文件正常
由此验证bean标签调用的是对象的无参构造,缺少无参构造函数则bean创建失败
2.Bean标签范围配置
scope:指对象的作用范围,取值如下:
scope标签中参数 singleton 和prototype的区别:
<bean id="a" class="com.dao.impl.AImpl" scope="singleton"/>
当bean标签中scope="singleton"时,如下图,两次取得的对象相同
A a = app.getBean(A.class); A a1 = app.getBean(A.class); System.out.println(a); System.out.println(a1);
当bean标签中scope="prototype"时,每次getBean取得的对象不同
<bean id="a" class="com.dao.impl.AImpl" scope="prototype"/>
由此引出下面的内容
3.scope="singleton"和 scope="prototype" 导致bean的创建时期不同
bean由无参构造创建
singleton 加载完配置文件bean创建但是bean并未被获取(getBean方法即为获取)
prototype 加载完配置文件bean没有被创建 获取时bean被创建
4.bean生命周期配置
init-method:指定类中初始化方法名称
destroy-method:指定类中销毁方法名称
<bean id="a" class="com.dao.impl.AImpl" init-method="A" destroy-method="B"/>
5.bean实例化的三种方式
1.无参构造方法实例化
2.工厂静态方法实例化
3.工厂实例方法实例化
工厂静态方法实例化
1.创建工厂类(内有实例化对象的静态方法)
public class StaticFactory { public static UserDao getUserDao(){ return new UserDaoImpl(); } }
<bean id="userDaoFactory" class="com.factory.StaticFactory" factory-method="getUserDao" />
工厂实例方法实例化
创建工厂类(内有动态实例化对象方法)
public class DynamicFactory { public UserDao getUserDao(){ return new UserDaoImpl(); } }
先通过无参构造方法创建动态工厂bean,即先实例化工厂bean再去调用当中的方法
<bean id="factory" class="com.factory.DynamicFactory"/>
<bean id="userDaofactory" factory-bean="factory" factory-method="getUserDao" />
spring配置数据源
1.数据源(连接池的作用)
数据源(连接池)是提高程序性能出现的
事先实例化数据源,初始化部分连接资源
使用连接资源时从数据源中获取
使用完毕后将连接资源归还给数据源
常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid等
2.数据源的开发步骤
1.导入数据源的坐标与数据库驱动坐标(这里使用C3P0和mysql8.0版本)
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency>
2.创建数据源的对象(在spring配置文件中)
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" ></bean>
3.设置数据源的基本连接数据(这里采用抽取jdbc.properties配置文件)
配置jdbc文件
jdbc.driver:com.mysql.cj.jdbc.Driver jdbc.url:jdbc:mysql://localhost:3306/test jdbc.username:root jdbc.password:1234
引入context命名空间,加载properties配置文件并配置数据源信息
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd <--location中要加classpath,不然找不到jdbc.properties--> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
4.使用数据源获取连接资源和归还连接资源
DataSource bean = app.getBean(DataSource.class); Connection connection = bean.getConnection(); System.out.println(connection); connection.close();
分模块开发
引入其它配置文件(分模块开发)
在spring核心配置文件中可以引入子配置文件
<import resource="applicationContext-user.xml" /> <import resource="applicationContext-product.xml" />
spring相关API
1.ApplicationContext的继承体系
2.getBean()方法
第一种方法传入一个自定义id,由于id唯一,当存在两个相同类型的bean时可以区分
第二种方法传入相应的字节码文件,不能区分两个相同类型的bean
第二种方式不需要类型的强转
第一种,适用于配置文件含有多个相同bean,第二种适用于配置文件中bean的类型唯一
依赖注入
之前是在UserService实现类中通过getBean的方式获取UserDao的实现类对象。
因为UserSerive和UserDao都在spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部
2.Bean的依赖注入概念
依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
3.依赖注入的两种方法(构造方法和set方法)
1.set方法注入
编写UserDao接口
public interface ADao { public void a(); }
编写ADaoImpl
public class ADaoImpl implements ADao { @Override public void a() { System.out.println(1); } }
编写AService接口
public interface Aservice { void A(); }
编写AServiceImpl实现类
用set方法实现依赖注入,AServiceImpl中一定要有set方法
private ADao aDao; public void setaDao(ADao aDao) { this.aDao = aDao; }
public class AServiceImpl implements Aservice { private ADao aDao; public void setaDao(ADao aDao) { this.aDao = aDao; } @Override public void a() { aDao.a(); } }
在spring配置文件中将ADao注入到AService中
<bean id="aDao" class="com.dao.impl.ADaoImpl" /> <bean id="aService" class="com.service.impl.AServiceImpl"> <property name="aDao" ref="aDao" /> </bean>
进行相关测试
Aservice bean = app.getBean(Aservice.class);
bean.a();
p命名空间注入
P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中
1.引入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p.xsd
<bean id="aDao" class="com.dao.impl.ADaoImpl" />
<bean id="aService" class="com.service.impl.AServiceImpl" p:aDao-ref="aDao">
</bean>
2.有参构造方法注入
<bean id="aDao" class="com.dao.impl.ADaoImpl" />
<bean id="aService" class="com.service.impl.AServiceImpl" >
<constructor-arg ref="aDao" />
</bean>
4.普通数据类型的注入
同样是set方法注入,所以需要写set方法
<bean id="userDao" class="com.dao.impl.UserDaoImpl">
<property name="age" value="18" ></property>
<property name="username" value="张三"></property>
</bean>
5.集合的注入
同样是set方法注入,所以需要写set方法
<bean id="userDao" class="com.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="userMap">
<map>
<entry key="u1" value-ref="user1">
</entry>
<entry key="u2" value-ref="user2"></entry>
</map>
</property>
<property name="properties">
<props >
<prop key="p1">ppp1</prop>
<prop key="p2">ppp2</prop>
<prop key="p3">ppp3</prop>
</props>
</property>
</bean>
<bean id="user1" class="com.model.User">
<property name="name" value="tom"></property>
<property name="addr" value="北京"></property>
</bean>
<bean id="user2" class="com.model.User">
<property name="name" value="jerry"></property>
<property name="addr" value="天津"></property>
</bean>
spring注解开发
1.spring原始注解
spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解替代xml配置文件可以简化配置,提高开发效率
spring原始注解主要是替代bean标签的配置
2.包扫描
使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包极其子包下的Bean需要扫描以便识别使用注解配置的类、字段、方法。
<!-- 配置组件扫描-->
<!-- 配置基础包,它和它的子包都会被扫描-->
<context:component-scan base-package="com">
</context:component-scan>
3.原始注解详解
@Component 类上实例化bean(交由容器完成bean的创建)
@Controller web层类上实例化bean
@Service 使用在service层类上用于实例化bean
@Repository dao层上实例化bean
bean对象使用注解配置 set方法可以省略
只写@Autowired //按照数据类型从Spring容器中进行匹配(userDao有多个时失效)
@Qualifier("userDao") //按照id值从容器中进行匹配的但是注意此处@Qualifier要结合@Autowired 一起使用
@Resource(name="userDao")相当于@Autowired+Qualifier("userDao")
4.spring新注解
创建一个配置类AConfig
@Configuration @ComponentScan("com") @Component("A") @PropertySource("classpath:jdbc.properties") public class AConfig { public AConfig() { } @Value("20") private int id; public Integer getID(){ return id; } @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource=new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } }
public static void main(String[] args) throws PropertyVetoException { //注意:实现类为AnnotationConfigApplicationContext 参数不再是一个配置文件,而是一个配置类 ApplicationContext app=new AnnotationConfigApplicationContext(AConfig.class); AConfig a =(AConfig) app.getBean("A"); DataSource dataSource = a.getDataSource(); System.out.println(1); System.out.println("datasource"+dataSource); System.out.println("id="+a.getID()+a.getID().equals(20)); }
spring集成Junit
使用main方法测试时
让SpringJunit负责创建Spring容器,但需要将配置文件的名称告诉它
开发步骤
1.引入相关坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2.使用@Runwith注解替换原来的运行期(参数为SpringJUnit4ClassRunner.class)
@RunWith(SpringJUnit4ClassRunner.class)
3.使用ContextConfiguration指定配置文件或配置类
@ContextConfiguration("classpath:applicationContext.xml")
<--加载配置类的方式-->
@ContextConfiguration("classes={SpringConfiguration.class}")
4.使用@Autowired注入需要测试的对象
@Autowired
private DemoService demoService;
5.进行测试
@Test
public void test1(){
demoService.show1();
}