一、Spring简介
为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码
Question: 什么是POJO、JavaBean,EJB?以及三者的区别。
JavaBean是一个遵循特定写法的Java类,它通常具有如下特点:
- 这个Java类必须具有一个无参的构造函数
- 属性必须私有化。
- 私有化的属性必须通过public类型的方法暴露给其它程序,并且方法的命名也必须遵守一定的命名规范。
二、IoC容器
2.1 工厂模式
? 在学习IoC容器之前,必须学习工厂模式的思想,这是设计模式相关的知识。
2.2 IoC概念
IoC,是 Inversion of Control 的缩写,即控制反转。
? IoC 不是什么技术,而是一种设计思想。在 Java 开发中,IoC 意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解 Ioc 呢?理解 Ioc 的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
- 谁控制谁,控制什么:传统 JavaSE 程序设计,我们直接在对象内部通过 new 进行创建对象,是程序主动去创建依赖对象;而 IoC 是有专门一个容器来创建这些对象,即由 IoC 容器来控制对象的创建;谁控制谁?当然是 IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
- 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
DI,是 Dependency Injection 的缩写,即依赖注入。
依赖注入是 IoC 的最常见形式。
容器全权负责的组件的装配,它会把符合依赖关系的对象通过 JavaBean 属性或者构造函数传递给需要的对象。
在 Spring 中,有两种 IoC 容器:BeanFactory 和 ApplicationContext 。
BeanFactory :Spring 实例化、配置和管理对象的最基本接口。ApplicationContext :BeanFactory 的子接口。它还扩展了其他一些接口,以支持更丰富的功能,如:国际化、访问资源、事件机制、更方便的支持 AOP、在 web 应用中指定应用层上下文等。
实际开发中,更推荐使用 ApplicationContext 作为 IoC 容器,因为它的功能远多于 BeanFactory 。
org.springframework.context.ApplicationContext 接口代表 Spring IoC 容器,并负责实例化,配置和组装 Bean。
2.3 IoC容器配置
IoC 容器的配置有三种方式:
- 基于 xml 配置
- 基于注解配置
- 基于 Java 配置
2.4 XML配置
2.4.1 基本配置
基于 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="..." class="...">
</bean>
<bean id="..." class="...">
</bean>
</beans>
- (1)
id 属性是标识单个 bean 定义的字符串。 - (2)
class 属性定义 bean 的类型并使用完全限定的类名。
Bean命名约定:bean 名称以小写字母开头,并从那里用驼峰式大小写。这样的名称的示例包括accountManager ,accountService ,userDao ,loginController 等
2.4.2 范围配置
2.4.3 实例化容器
提供给ApplicationContext 构造函数的位置路径是资源字符串,这些资源字符串使容器可以从各种外部资源(例如本地文件系统,Java CLASSPATH 等)加载配置元数据。
通常,在容器本身通过反射性地调用其构造函数直接创建 Bean 的情况下,指定要构造的 Bean 类,这在某种程度上等效于new 运算符的 Java 代码。
例如:
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
2.4.4 例子
package ioc.xmlConfig;
public class Hello {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void show(){
System.out.println("Hello "+name);
}
}
<?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="hello" class="ioc.xmlConfig.Hello">
<property name="name" value="Spring"/>
</bean>
</beans>
package ioc.xmlConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
}
2.5 注解配置
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。 Spring 默认是不启用注解的。如果想使用注解,需要先在 xml 中启动注解。启动方式:在xml文件中启用context命名空间,并加入以下标签:
<context:annotation-config/>
@Required 注解只能用于修饰 bean 属性的 setter 方法。@Autowired 注解可用于修饰属性、setter 方法、构造方法。@Autowired注解用于实现自动装配,一般情况下,它可以替换为@Inject。
2.5.1 Spring原始注解
Spring原始注解主要是替代<Bean> 的配置
@Required 注解只能用于修饰 bean 属性的 setter 方法。@Autowired 注解可用于修饰属性、setter 方法、构造方法。@Autowired注解用于实现自动装配,一般情况下,它可以替换为@Inject。
2.5.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"
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:component-scan base-package="AnnotationConfig"/>
</beans>
public interface UserDao {
void request();
}
@Component("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void request() {
System.out.println("request running...");
}
}
@Component("userService")
public class UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void request(){
userDao.request();
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext-anno.xml")
public class MyTest {
@Autowired
private UserService userService;
@Test
public void test(){
userService.request();
}
}
2.5.3 Spring新注解
2.6 Java配置
(注:在《Spring实战》(第四版)中作者将不使用xml文件的注解配置称为Java配置,在一些培训班课程如黑马程序员的视频课程中还是将其称为注解配置。)
? 在进行显式配置时,JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。因为它就是Java代码,就像应用程序中的其他Java代码一样。
? 基于 Java 配置 Spring IoC 容器,实际上是 Spring 允许用户定义一个类,在这个类中去管理 IoC 容器的配置。为了让 Spring 识别这个定义类为一个 Spring 配置类,需要用到两个注解:@Configuration 和@Bean 。创建JavaConfig类的关键在于为其添加@Configuration注解,@Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。
? @Bean 注解 与<bean/> 元素具有相同的作用。您可以对任何 Spring @Component 使用@Bean 注解 的方法。但是,它们最常与@Configuration bean 一起使用。
? AnnotationConfigApplicationContext 类用于实例化使用注解配置的IoC容器
package ioc.javaConfig;
public class Hello {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void show(){
System.out.println("Hello "+name);
}
}
package ioc.javaConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class beanFactory {
@Bean
public Hello myHello(){
return new Hello();
}
}
package ioc.javaConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(beanFactory.class);
Hello hello = context.getBean(Hello.class);
hello.setName("Spring");
hello.show();
}
}
|