Spring是一个开源免费的框架,为了解决企业应用开发的复杂性而创建。Spring框架是一个轻量级的解决方案,可以一站式地构建企业级应用。Spring是模块化的,所以可以只使用其中需要的部分。可以在任何web框架上使用控制反转(IoC),也可以只使用Hibernate集成代码或JDBC抽象层。它支持声明式事务管理、通过RMI或web服务实现远程访问,并可以使用多种方式持久化数据。它提供了功能全面的MVC框架,可以透明地集成AOP到软件中。
Spring被设计为非侵入式的,这意味着你的域逻辑代码通常不会依赖于框架本身。在集成层(比如数据访问层),会存在一些依赖同时依赖于数据访问技术和Spring,但是这些依赖可以很容易地从代码库中分离出来。
Spring框架是基于Java平台的,它为开发Java应用提供了全方位的基础设施支持,并且它很好地处理了这些基础设施,所以你只需要关注你的应用本身即可。
Spring可以使用POJO(普通的Java对象,plain old java objects)创建应用,并且可以将企业服务非侵入式地应用到POJO。这项功能适用于Java SE编程模型以及全部或部分的Java EE。
那么,做为开发者可以从Spring获得哪些好处呢?
不用关心事务API就可以执行数据库事务;
不用关心远程API就可以使用远程操作;
不用关心JMX API就可以进行管理操作;
不用关心JMS API就可以进行消息处理。
①JMX,Java Management eXtension,Java管理扩展,是一个为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
②JMS,Java Message Service,Java消息服务,是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。
一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
官网: http://spring.io
文档: https://docs.spring.io/spring/docs/current/spring-framework-reference/、 https://github.com/waylau/spring-framework-4-reference
中文帮助: http://spring.cndocs.ml/
框架下载地址: http://repo.springsource.org/libs-release-local/org/springframework/spring/
教程: http://www.yiibai.com/spring
Git: https://github.com/spring-projects
源码: https://github.com/spring-projects/spring-framework
Jar包: https://github.com/spring-projects/spring-framework/releases
2002年,Rod Jahnson在《Expert One-on-One J2EE Design and Development》书中首次推出了Spring框架雏形interface21框架。
2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。
从2004年3月到现在,已经经历了1.0、1.1、1.2、2.0、2.5、3.0、3.1几个主要的版本
3.2.0版发布 2013年5月5日13:53
3.2.10版发布 2014年7月15日23:58
3.2.9版发布 2014年5月20日12:22
4.0.0版发布 2013年12月12日07:50
4.0.1版发布 2014年1月28日20:55
4.1.6版发布 2015年3月25日16:40
4.2.2版发布 2015年10月15日12:57
4.2.5版发布 2016年2月25日09:28
4.3.5版发布 2016年12月21日11:34
4.3.6版发布 2017年1月25日14:05
4.3.8版发布 2017年4月18日13:49
4.3.9版发布 2017年6月7日19:29
5.0.0版发布 2017年9月28日11:28
5.0.1版发布 2017年10月24日15:14
轻量:从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转Ioc:Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
面向切面Aop:Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器:Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
框架:Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
MVC:Spring的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架,Spring MVC是一个非常受欢迎的轻量级Web框架。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
BeanFactory
,它是工厂模式的实现。BeanFactory
使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。
Spring是一个开源的框架,现在的Spring框架构成了一个体系平台,通过Spring的官方网站http://www.springsource.org可以了解到,围绕着Spring框架本身,还有许多其他优秀的项目:
SpringFramework(Core):核心项目
Spring Web Flow:工作流项目
Spring Security:安全项目
Spring Batch:批量数据处理项目
Spring Android:Android系统支持项目
Spring Social:社交项目
Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。
SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
假设项目中需要完成对图书的数据访问服务,我们定义好了IUserDao接口与UserDaoImpl实现类。
创建maven项目:
IUserDao接口如下:
package cn.liuw.dao;
import cn.liuw.po.User;
/**
* @ClassName IUserDao
* @Description 用户数据访问接口
**/
public interface IUserDao {
/**
* 添加图书
*/
public void addUser(User user);
}
UserDaoImpl实现类如下:
package cn.liuw.dao.impl;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
/**
* @ClassName UserDaoImpl
* @Description TODO
**/
public class UserDaoImpl implements IUserDao{
@Override
public void addUser(User user) {
System.out.println(user);
}
}
Maven项目的pom.xml如下:
4.0.0
cn.lv
Learning-Spring
1.0-SNAPSHOT
war
Learning-Spring Maven Webapp
http://www.example.com
UTF-8
1.7
1.7
4.3.1.RELEASE
junit
junit
4.12
test
log4j
log4j
1.2.16
mysql
mysql-connector-java
5.1.35
org.springframework
spring-core
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-test
${spring.version}
test
org.springframework
spring-expression
${spring.version}
org.springframework
spring-aop
${spring.version}
org.aspectj
aspectjweaver
1.8.9
commons-dbcp
commons-dbcp
1.2.2
Learning-Spring
maven-clean-plugin
3.0.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.7.0
maven-surefire-plugin
2.20.1
maven-war-plugin
3.2.0
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
业务接口IUserService如下:
package cn.liuw.service;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
/**
* @ClassName IUserService
* @Description TODO
**/
public interface IUserService {
public void saveUser(User user);
}
业务实现类UserServiceImpl如下:
package cn.liuw.service.impl;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
import cn.liuw.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName UserServiceImpl
* @Description TODO
**/
public class UserServiceImpl implements IUserService{
IUserDao userDao;
public UserServiceImpl() {
//容器
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//从容器中获取id = userDao的bean
userDao = (IUserDao) context.getBean("userDao");
}
@Override
public void saveUser(User user) {
System.out.println("开始添加用户...");
userDao.addUser(user);
System.out.println("结束添加用户...");
}
}
容器的配置文件applicationContext.xml如下:
测试类Test如下:
import cn.liuw.po.User;
import cn.liuw.service.IUserService;
import cn.liuw.service.impl.UserServiceImpl;
import org.junit.Test;
/**
* @ClassName Test01
* @Description TODO
**/
public class Test01 {
@Test
public void testSaveUser(){
//手动创建IUserService对象
IUserService userService = new UserServiceImpl();
//创建一个User对象进行保存
User user = new User();
user.setId(1);
user.setUsername("张三");
user.setSex("男");
user.setAddress("石家庄裕华区");
//这里使用applicationContext.xml的IOC管理userService对象中的userDao对象
userService.saveUser(user);
}
}
运行结果:
开始添加用户...
User{id=1, username='张三', sex='男', birthday=null, address='石家庄裕华区'}
结束添加用户...
Process finished with exit code 0
如下所示,则上下文会使用无参构造方法创建对象
Person.java
package cn.liuw.po;
/**
* @ClassName Person
* @Description TODO
**/
public abstract class Person {
String name;
}
Student.java
package cn.liuw.po;
/**
* @ClassName Student
* @Description TODO
**/
public class Student extends Person{
private int height;
public Student(String name,int height) {
this.name = name;
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"height=" + height +
", name='" + name + '\'' +
'}';
}
}
测试类:
import cn.liuw.po.Person;
import cn.liuw.po.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName Test02
* @Description TODO
**/
public class Test02{
public static void main(String[] args) {
//IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
Person person = context.getBean(Student.class);
System.out.println(person);
}
}
配置文件applicationContext.xml:
运行结果:
Student{height=180, name='小明'}
Process finished with exit code 0
注意:如果在使用构造方法时不想通过参数名称指定参数则可以直接使用索引,如:
Address地址类:
package cn.liuw.po;
/**
* @ClassName Address
* @Description TODO
**/
public class Address {
//国家
private String country;
//城市
private String city;
public Address(){
}
public Address(String country, String city) {
this.country = country;
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"country='" + country + '\'' +
", city='" + city + '\'' +
'}';
}
}
配置文件applicationContext.xml:
测试类:
import cn.liuw.po.Address;
import cn.liuw.po.Person;
import cn.liuw.po.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName Test02
* @Description TODO
**/
public class Test02{
public static void main(String[] args) {
//IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
Address address = context.getBean(Address.class);
System.out.println(address);
}
}
运行结果:
Address{country='中国', city='石家庄'}
Process finished with exit code 0
使用scope属性可以指定作用域
配置文件applicationContext.xml:
测试类:
import cn.liuw.po.Address;
import cn.liuw.po.Person;
import cn.liuw.po.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName Test02
* @Description TODO
**/
public class Test02{
public static void main(String[] args) {
//IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
Address addr1 = (Address) context.getBean("address2");
Address addr2 = (Address) context.getBean("address2");
//默认一个bean对应一个单例的对象,但是id=address2这个bean设置了属性scope=prototype
System.out.println(addr1 == addr2);
}
}
运行结果:
false
Process finished with exit code 0
ApplicationContext
实现的默认行为是在启动时将所有singleton bean提前进行实例化。 如果你不想这样,你可以将单例bean定义为延迟加载防止它提前实例化。延迟初始化bean会告诉IOC容器在第一次需要的时候再实例化而不是在容器启动时就实例化。
配置文件applicationContext.xml:
测试类:
import cn.liuw.po.Address;
import cn.liuw.po.Person;
import cn.liuw.po.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName Test02
* @Description TODO
**/
public class Test02{
public static void main(String[] args) throws InterruptedException {
//IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("+++++++++++++++++++++++++");
//从容器中获取对象
Address address = (Address) context.getBean("address3");
System.out.println(address);
}
}
运行结果:
+++++++++++++++++++++++++
初始化...
Address{country='中国', city='石家庄'}
我们看到打印的"初始化..."是在"+++++++"后面的,这说明,在加载applicationContext.xml的时候并未创建id=address3的bean。
上一个示例是使用传统的xml配置完成IOC的,如果内容比较多则配置需花费很多时间,通过注解可以减轻工作量,但注解后修改要麻烦一些,耦合度会增加,应该根据需要选择合适的方法。
修改上面的UserDaoImpl类,添加注解@Component:
package cn.liuw.dao.impl;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
import org.springframework.stereotype.Component;
/**
* @ClassName UserDaoImpl
* @Description TODO
**/
@Component("userDao")
public class UserDaoImpl implements IUserDao{
@Override
public void addUser(User user) {
System.out.println(user);
}
}
在类上增加了一个注解Component,在类的开头使用了@Component注解,它可以被Spring容器识别,启动Spring后,会自动把它转成容器管理的Bean。
除了@Component外,Spring提供了3个功能基本和@Component等效的注解,分别对应于用于对DAO,Service,和Controller进行注解。
1:@Repository 用于对DAO实现类进行注解。
2:@Service 用于对业务层注解,但是目前该功能与 @Component 相同。
3:@Constroller用于对控制层注解,但是目前该功能与 @Component 相同。
修改以上的UserServiceImpl类,添加@Compotent注解:
package cn.liuw.service.impl;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
import cn.liuw.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
/**
* @ClassName UserServiceImpl
* @Description TODO
**/
@Component("userService")
public class UserServiceImpl implements IUserService{
IUserDao userDao;
@Override
public void saveUser(User user) {
//容器
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//从容器中获取id = userDao的bean
userDao = (IUserDao) context.getBean("userDao");
System.out.println("开始添加用户...");
userDao.addUser(user);
System.out.println("结束添加用户...");
}
}
以上添加了@Component注解,同时将无参构造方法中的语句放到了saveUser()方法中。避免无限循环加载Spring配置文件。
修改applicationContext.xml配置文件:
运行结果:
开始添加用户...
User{id=1, username='张三', sex='男', birthday=null, address='石家庄裕华区'}
结束添加用户...
从上一个示例中可以看出有两个位置都使用了ApplicationContext初始化容器后获得需要的Bean,可以通过自动装配简化。
修改UserDaoImpl类的注解为:@Repository更为准确。
@Repository("userDao")
public class UserDaoImpl implements IUserDao{
@Override
public void addUser(User user) {
System.out.println(user);
}
}
修改UserServiceImpl类的注解为:@Service更为准确,同时为userDao属性添加上注解@AutoWired。
@Service("userService")
public class UserServiceImpl implements IUserService{
@Autowired
IUserDao userDao;
@Override
public void saveUser(User user) {
System.out.println("开始添加用户...");
userDao.addUser(user);
System.out.println("结束添加用户...");
}
}
@Autowired注解的作用是:可以对成员变量、方法和构造函数进行注解,来完成自动装配的工作,通俗来说就是会根据类型从容器中自动查到到一个Bean给userDao字段。@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier。另外可以使用其它注解,@Resource :等同于@Qualifier,@Inject:等同于@Autowired。
@Service用于注解业务层组件(我们通常定义的service层就用这个)
@Controller用于注解控制层组件(如struts中的action)
@Repository用于注解数据访问组件,即DAO组件
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行注解。
装配注解主要有:@Autowired、@Qualifier、@Resource,它们的特点是:
1、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
2、@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
3、@Resource注解是又J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;如果Maven项目是1.5的JRE则需换成更高版本的。
4、@Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上
5、@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。
6、@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。
7、@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要。
8、@Resource装配顺序
8.1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
8.2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
8.3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
8.4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
package cn.liuw.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class InjectTest {
//注入给构造方法
@Autowired
public InjectTest(IUserDao dao2) {
this.dao2=dao2;
}
//注入给成员变量,字段
@Resource
IUserDao dao1;
IUserDao dao2;
IUserDao dao3;
IUserDao dao4;
//注入给属性
@Autowired
public void setDao3(IUserDao dao3) {
this.dao3 = dao3;
}
//注入给方法参数
@Autowired
public void injectDao4(IUserDao dao4, IUserDao dao5) {
this.dao4 = dao4;
System.out.println(dao5);
}
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("bookbean13.xml");
InjectTest obj = ctx.getBean(InjectTest.class);
System.out.println(obj.dao1);
System.out.println(obj.dao2);
System.out.println(obj.dao3);
System.out.println(obj.dao4);
}
}
interface IUserDao {
}
@Scope("prototype")
@Repository
class UserDao implements IUserDao {
}
运行结果:
cn.liuw.service.OrderDao@711a924b
cn.liuw.service.OrderDao@1442df6c
cn.liuw.service.OrderDao@325a35d8
cn.liuw.service.OrderDao@408511bb
cn.liuw.service.OrderDao@604f2d14
package cn.liuw.boot;
import cn.liuw.po.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName Applicationfg
* @Description TODO
**/
@Configuration
@ComponentScan(basePackages = "cn.liuw")
public class ApplicationCfg {
}
@Configuration相当于配置文件中的
测试类:
import cn.liuw.boot.ApplicationCfg;
import cn.liuw.po.User;
import cn.liuw.service.IUserService;
import cn.liuw.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @ClassName Test03
* @Description TODO
**/
public class Test03 {
@Test
public void testSaveUser(){
//获取容器
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationCfg.class);
//从容器中获取UserServiceImpl对象
IUserService userService = context.getBean(UserServiceImpl.class);
//创建User对象
User user = new User();
user.setId(1);
user.setUsername("张三");
user.setSex("1");
user.setAddress("河北邯郸");
userService.saveUser(user);
}
}
运行结果:
开始添加用户...
User{id=1, username='张三', sex='1', birthday=null, address='河北邯郸'}
结束添加用户...
零配置@Bean案例:
@Bean相当于
@Configuration
@ComponentScan(basePackages = "cn.liuw")
public class ApplicationCfg {
@Bean
public User getUser(){
return new User();
}
}
测试类:
@Test
public void testUser(){
//容器
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationCfg.class);
User user1 = context.getBean("getUser",User.class);
System.out.println(user1);
}
运行结果:
User{id=0, username='null', sex='null', birthday=null, address='null'}
package cn.liuw;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
public class NoXMLIoC {
public static void main(String[] args) {
//基于类型的配置
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppCfg.class);
ICarDao dao1=ctx.getBean(ICarDao.class);
dao1.add("Spring Pro");
}
}
interface ICarDao{
void add(String name);
}
@Repository
class CarDao implements ICarDao{
public void add(String name) {
System.out.println("添加"+name+"成功!");
}
}
@Configuration
@ComponentScan(basePackages = "spring14")
class AppCfg{
}
package cn.liuw;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
public class NoXMLIoC {
public static void main(String[] args) {
//基于类型的配置
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppCfg.class);
ICarDao dao2=ctx.getBean("mysqlDao",ICarDao.class);
dao2.add("Spring Pro");
}
}
interface ICarDao{
void add(String name);
}
class CarDao implements ICarDao{
public void add(String name) {
System.out.println("添加"+name+"成功!");
}
}
@Configuration
@ComponentScan(basePackages = "spring14")
class AppCfg{
@Bean
ICarDao mysqlDao(){ //方法名就是bean的name
return new CarDao();
}
}
@value注解可以实现为对象赋值,可以直接指定值也可以从properties文件中获取,这里主要讲解两种方式:
1. 在resource目录下创建一个properties文件,如db.properties:
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=1234
2. 在Spring配置文件中导入资源文件
3. 通过@Value引用资源文件中的内容
package cn.liuw.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @ClassName DBUtil
* @Description TODO
**/
@Component
public class DBUtil {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("${jdbc.jdbcUrl}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "DBUtil{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
4. 测试类
public class Test04 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DBUtil dbUtil = ctx.getBean(DBUtil.class);
System.out.println(dbUtil);
}
}
5. 运行结果
DBUtil{driver='com.mysql.jdbc.Driver', url='jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8', username='root', password='1234'}
1. 创建配置类
@Configuration
@ComponentScan("cn.liuw")
@PropertySource("db.properties")
public class SpringCfg {
}
2. 测试类
public class Test04 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringCfg.class);
IUserDao userDao = ctx.getBean(UserDaoImpl.class);
//创建User对象
User user = new User();
user.setId(1);
user.setUsername("李四");
user.setAddress("北京市");
//添加user
userDao.addUser(user);
}
}
3.运行结果
User{id=1, username='李四', sex='null', birthday=null, address='北京市'}
本文参考自:https://www.cnblogs.com/best/p/5727935.html