1.Spring简介
2.IOC 控制反转
3.IOC创建对象的方式
4.Spring配置
5.属性注入以bean的作用域
6.自动装配
7.注解开发
8.Java方式配置Spring
1.Spring简介
简单的说spring是一个轻量级的控制反转(IOC) 和面向切面编程(AOP)的框架!是程序员的春天,是软件行业的春天。
- 由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Rod Johnson ,Spring Framework创始人,著名作者。悉尼大学音乐学博士。
- 2002,首次推出了Spring框架的雏形:interface21框架!
- Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于*2004年3月24日,*发布了1.0正式版。
三个重要的网站:
官网:https://spring.io/projects/spring-framework#overview
官方下载地址: http://repo.spring.io/release/org/springframework/spring
GitHub:https://github.com/spring-projects/spring-framework
1.1 优点
- 开源的免费的框架(容器)!
- 轻量级的、非入侵式的框架!
- 控制反转(IOC) , 面向切面编程(AOP)!
- 支持事务的处理,对框架整合的支持!
1.2 组成
核心容器
提供了依赖注入(DependencyInjection)特征来实现容器对Bean的管理。
应用上下文(Context)模块
上下文模块使它成为一个框架,这个模块提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务
Spring的AOP模块
提供了对面向切面编程的丰富支持。
JDBC抽象和DAO模块
Spring的JDBC和DAO模块抽取取得连接、创建语句、处理结果集,关闭连接这些重复代码,使数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。
对象/关系映射集成模块
为几种流行的ORM框架提供了集成方案。
Spring的Web模块
提供了一个适合于Web应用的上下文,它也提供了Spring和其它Web框架的集成。
Spring的MVC框架
Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。
现代化的Java开发!就是基于Spring的开发!,他的官网介绍就是构建一切,协调一切,连接一切。
2.IOC
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
2.1 IOC实现
mapper接口类
public interface UserMapper {
public void getUser();
}
mapper实现类
public class UserMapperImpl implements UserMapper{
public void getUser() {
System.out.println("11111");
}
}
service接口类
public interface UserService {
public void getUser();
}
service实现类
public class UserServiceImpl implements UserService {
private UserMapper userMapper = new UserMapperImpl();
public void getUser() {
}
}
测试
public class test {
@Test
public void test(){
Service service = new ServiceImpl();
service.getUser();
}
}
增加mapper实现类
public class UserMapperSqlImpl implements UserMapper {
public void getUser() {
System.out.println("sql");
}
}
用新的实现类,修改service里的实现类就好,
public class ServiceImpl implements Service {
private UserMapper userMapper = new UserMapperSqlImpl();
public void getUser() {
mapper.getUser();
}
}
在增加一个mapper实现类
public class UserOracleImpl implements UserMapper {
public void getUser() {
System.out.println("oracle");
}
}
要实现这个,依旧需要在service里修改实现,这样在代码要求非常多的情况下,每次都需要大量的改动,传统new对象的逻辑开发,原来是程序员操作的,现在
用set方法!对外提供接口,程序不用管理实现,主动权交给用户,自己set调用dao层,不是写死程序,而是对外提供接口面向接口编程,程序不用管理,只需要提供接口。
在用户实现类增加set方法
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void getUser() {
}
}
测试类增加了用户操作权限
public class test {
@Test
public void test(){
//UserMapperImpl userMapper = new UserMapperImpl();
// UserMapperSqlImpl userMapper = new UserMapperSqlImpl();
UserOracleImpl userMapper = new UserOracleImpl();
//用户多了可以自己操作的权限
UserServiceImpl service = new UserServiceImpl();
service.setUserMapper(userMapper);
service.getUser();
}
}
解耦,这就是IOC的原型
2.2 Hello
一共就三步1.导入依赖2.编写配置文件3.注册bean
1.导入依赖
maven中导入依赖的时候,会帮我们自动下载相关的依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.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就是java对象 , 由Spring创建和管理-->
<bean id="hello" class="com.yang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
</beans>
3.注册bean
public class test {
@Test
public void testHelloSpring(){
//解析xml文件 , 生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//getBean : 参数即为spring配置文件中bean的id
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
}
这个过程就叫控制反转 :
控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 .
反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想 , 由主动的编程变成被动的接收 .
3.IOC创建对象的方式
3.1 无参构造
set方法 p命名注入 默认方式
配置文件
<bean id="user" class="com.yang.pojo.User">
<property name="name" value="Spring"/>
</bean>
bean注册
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User) context.getBean("user");
user.show();
}
在配置文件加载的时候,容器中管理的对象就已经初始化了!
3.2 有参构造
构造器注入 c命名注入
1.参数名赋值 普通的注入方式
<bean id="user" class="com.yang.pojo.User">
<constructor-arg name="name" value="yyy"/>
</bean>
2.类型
当参数只有一个时,可以根据类型来;当有多个参数且类型不一致时,不好用
<bean id="user" class="com.yang.pojo.User">
<constructor-arg type="java.lang.String" value="liuyangyang"/>
</bean>
3.小标赋值
第一个参数的index从0开始
<bean id="user" class="com.yang.pojo.User">
<constructor-arg index="0" value="yangyang"/>
</bean>
测试:
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User) context.getBean("user");
user.show();
}
4.Spring配置
4.1 alias别名
<!--别名,如果添加了别名,我们也可以使用别名获取到这个对象-->
<alias name="user" alias="userNew"/>
4.2 bean和beans
<!--
id : bean 的唯一标识符,也就是相当于我们学的对象名
class : bean 对象所对应的全限定名 : 包名 + 类型
name :也是别名,而且name 可以同时取多个别名
-->
<bean id="user" class="com.yang.pojo.User" name="user2 u2,u3;u4">
<property name="name" value="洋洋"/>
</bean>
4.3 import
一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
<import resource="st.xml"/>
<import resource="user.xml"/>
5.属性注入以bean的作用域
5.1 属性注入
依赖注入:Set注入!
- 依赖:bean对象的创建依赖于容器!
- 注入: bean对象中的所有属性,由容器来注入!
复杂实体类
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
测试对象
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> list;
private Map<String,String> map;
private Set<String> set;
private String wife ;// null
private Properties info;
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setBooks(String[] books) {
this.books = books;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setWife(String wife) {
this.wife = wife;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.getAddress() +
", books=" + Arrays.toString(books) +
", list=" + list +
", map=" + map +
", set=" + set +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
xml配置
全局xml :学生xml需要注册到全局xml中
<import resource="st.xml"/>
学生类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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="addr" class="com.yang.pojo.Address">
<property name="address" value="西安"/>
</bean>
<bean id="student" class="com.yang.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="洋洋"/>
<property name="address" ref="addr"/>
<!--数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!--List-->
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<!--Map-->
<property name="map">
<map>
<entry key="k1" value="v1"/>
<entry key="k2" value="v2"/>
</map>
</property>
<!--Set-->
<property name="set">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!--null值注入-->
<property name="wife">
<null/>
</property>
<!--Properties 配置类-->
<property name="info">
<props>
<prop key="id">100</prop>
<prop key="sex">girl</prop>
<prop key="name">小明</prop>
</props>
</property>
</bean>
</beans>
测试类
@Test
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
Student student = (Student)context.getBean("student");
System.out.println(student.toString());
}
}
5.2 bean的作用域
1.singletion模式中 测试两次getbean的hashcode值是否一样
@Test
//属性注入
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
Student student = (Student)context.getBean("student");
Student student2 = (Student)context.getBean("student");
System.out.println(student.hashCode());
System.out.println(student2.hashCode());
}
2.prototype模式中,测试两次getbean的hashcode值是否一样
6.自动装配
6.1测试
entity包下三个实体类
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
public class User {
private String name;
private Cat cat;
private Dog dog;
public void setName(String name) {
this.name = name;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public String getName() {
return name;
}
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", cat=" + cat + ", dog=" + dog + '}';
}
}
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<bean id="user" class="com.yang.entity.User" autowire="byName">
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
<property name="name" value="yangyang"/>
</bean>
</beans>
测试:
@Test
//5.自动装配
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User)context.getBean("user");
System.out.println(user);
user.getCat().shout();
user.getDog().shout();
}
6.2自动装配
ByName
byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的 bean!
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<bean id="user" class="com.yang.entity.User" autowire="byName">
<!--<property name="cat" ref="cat"/>-->
<!--<property name="dog" ref="dog"/>-->
<property name="name" value="yangyang"/>
</bean>
测试结果:
错误情况:
ByType
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<!--<bean id="cat2" class="com.yang.entity.Cat"/>-->
<bean id="user" class="com.yang.entity.User" autowire="byType">
<property name="name" value="yangyang"/>
</bean>
会自动在容器上下文中查找,和自己对象属性类型相同的bean!需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
错误情况:
但是在开发中一般使用注解自动装配!
6.3注解自动装配
为了使用注解,使用新的约束文件
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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.增加 xmlns:context="http://www.springframework.org/schema/context"
2. http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
3.配置注解支持 <context:annotation-config/>
-->
<context:annotation-config/>
</beans>
@Autowired
public class People {
//如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
@Resource注解
public class People {
private String name;
@Autowired(required = false) //表示允许对象为null ,默认是true
private Cat cat;
@Resource //也可以通过这个
private Dog dog;
}
小结:
@Resource 和@ Autowired 的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @ Autowired 通过byType的方式实现,而且必须要求这个对象存在! 【常用】
- @ Resource 默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错! 【常用】
- 执行顺序不同:@ Autowired 通过byType的方式实现。@ Resource 默认通过byname的方式实现。
7.注解开发
1.必须要有aop的包
2.context约束
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.yang.pojo"/>
</beans>
3.bean属性注入
可以放在字段属性上,可以放在方法上,不过一般放在属性上。
@Component("user")
//相当于<bean id=user/>
public class User {
//public String name = "liuyang";
@Value("LIUYANG")
public String name;
//相当于 <property name="name" value="LIUYANG"/>
@Value("LIUYANG2")
public void setName(String name) {
this.name = name;
}
}
4.component的三个等价注解
我们在web开发中,会按照mvc三层架构分层!
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
5.小结
xml 与 注解:
- xml 更加万能,适用于任何场合!维护简单方便
- 注解 不是自己类使用不了,维护相对复杂!
xml 与 注解最佳实践:
- xml 用来管理bean;
- 注解只负责完成属性的注入;
- 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
8.Java方式配置Spring
1.实体类
@Component //说明这个类被Spring接管了,注册到了容器中
public class Dog {
@Value("小黑")//也可以
private String name;
}
2.配置类
@Configuration //代表这个类是配置类
public class myapplication {
@Bean //返回一个bean id=方法名 class=具体返回对象
public Dog dog(){
return new Dog();
}
}
3.测试类
@Test
public void test7(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(myapplication.class);
Dog dog = (Dog) context.getBean("dog");
System.out.println(dog.name);
}
4.将两个配置类联系在一起
- 一个新的配置类:
@Configuration
public class myconfiguration {
}
- 将两个配置类联系在一起:
@Import(myconfiguration.class)
@Configuration //代表这个类是配置类
@Import(myconfiguration.class)
public class myapplication {
@Bean //返回一个bean id=方法名 class=具体返回对象
public Dog dog(){
return new Dog();
}
}
但是传统的开发框架还是用xml居多。