Spring
Spring是一个分层的轻量级Java开发框架,位于业务层,核心是控制反转(IoC)和面向切面(AOP)。
IoC技术将所有对象交给Spring统一管理。
IoC
控制反转(Inversion of Control,IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。将对象的创建、销毁权反转给Spring。
DI
依赖注入(Dependency Injection,DI),在Spring框架负责创建Bean对象时,动态地将依赖对象注入到Bean对象中。
Spring配置IoC的三种方式:
1. 加载配置文件+在配置文件applicationContext.xml中配置Bean标签管理
加载配置文件
// 方法一:使用Spring的工厂,加载类路径下的Spring配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类对象
UserService userService = (UserService) applicationContext.getBean("userService");
//方法二:注解方式使用Spring的工厂,加载类路径下的Spring配置文件
@ContextConfiguration(value = "classpath:applicationContext_test.xml") // 加载类路径下的配置文件
<!--方法三:web项目使用web.xml文件加载-->
<!-- 配置spring的监听器,加载applicationContext.xml配置文件-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置加载类路径的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
Bean标签常用属性:
id:Bean的名字,具有唯一性
name:用于指定Bean的别名
class:用于指定Bean的来源,即对应的类(全名)
scope:用于指定bean的模式。
singleton:是单例模式,容器只创建一个对象,默认值
prototype:为非单例模式,容器创建多个对象,但容器不会去逐个销毁
request:web项目中spring创建一个bean对象,将对象存到request域中
session: web项目中将对象存到session域中
globalSession:web项目中,把对象放到globalSession域里面,应用在prolet环境,如果没有prolet环境那么globalSession相当于session
property:配置自动注入JavaBean的成员变量
autowire:配置Spring对象属性的默认装配方式。
no:不启动自动装配,默认值
byType:根据类型自动装配
byName:根据名称自动装配,name未声明时则默认使用id值
init-method:Bean的初始化方法,当Bean被载入到容器的时候调用
destory-method:Bean的销毁方法,当Bean从容器中删除的时候调用,只在scope= singleton有效
lazy-init:用于指定Bean的初始化时间。值为true表示在初次调用时才会自动创建实例并初始化;值为false表示在IoC容器创建的时候就会完成创建和初始化,默认是false
实例化Bean对象的三种方式:
(1)默认是无参数的构造方法(最常用)
<bean id="us" class="cn.service.UserServiceImpl" />
(2)静态工厂实例化
package cn.demo1;
import cn.service.UserService;
import cn.service.UserServiceImpl;
public class StaticFactory {
public static UserService createUs(){
System.out.println("通过静态工厂的方式创建UserServiceImpl对象...");
// 编写业务逻辑 权限校验
return new UserServiceImpl();
}
}
<bean id="us" class="cn.demo1.StaticFactory" factory‐method="createUs" />
(3)动态工厂实例化
package cn.demo1;
import cn.service.UserService;
import cn.service.UserServiceImpl;
public class Dfactory {
public UserService createUs(){
System.out.println("实例化工厂的方式...");
return new UserServiceImpl();
}
}
<bean id="dfactory" class="cn.demo1.Dfactory" />
<bean id="us" factory‐bean="dfactory" factory‐method="createUs" />
配合Bean标签的DI依赖注入方式:
(1)属性的set方法注入值
(2)属性构造方法注入值
//依赖注入方法一:提供该属性的set方法,IOC容器底层就通过属性的set方法方式注入值
private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
//依赖注入方法二:构造方法依赖注入
private String msg;
private String age;
public OrderServiceImpl(String msg, String age) {
this.msg = msg;
this.age = age;
}
<bean id="orderService" class="cn.service.OrderServiceImpl">
<property name="orderDao" ref="orderDao"/>
<constructor-arg name="msg" value="你好"/>
<constructor-arg name="age" value="20"/>
</bean>
<bean id="orderDao" class="cn.service.OrderDaoImpl"></bean>
数组、容器、Properties 依赖注入举例:
package xy.service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollectionBean {
private String[] strs;
private List<String> list;
private Map<String,String> map;
private Properties properties;
public void setStrs(String[] strs) {
this.strs = strs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean{" +
"strs=" + Arrays.toString(strs) +
", list=" + list +
", map=" + map +
", properties=" + properties +
'}';
}
}
<bean id="collectionBean" class="xy.service.CollectionBean">
<property name="strs">
<array>
<value>美美</value>
<value>明明</value>
</array>
</property>
<property name="list">
<list>
<value>小新</value>
<value>猫咪老师</value>
</list>
</property>
<property name="map">
<map>
<entry key="a" value="小花"/>
<entry key="b" value="小猫"/>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">1234567</prop>
</props>
</property>
</bean>
2.加载配置文件+注解扫描+注解
加载配置文件同上
在applicationContext.xml中开启注解扫描
<context:component-scan base-package="cn"/><!--包名-->
IOC常用注解:
@Component 普通的类
@Controller 表现层
@Service 业务层
@Repository 持久层
依赖注入常用注解
@Value 用于注入普通类型(String,int,double等类型)
@Autowired 默认按类型进行自动装配(引用类型)
@Qualifier 和@Autowired一起使用,强制使用名称注入
@Resource Java提供的注解,也被支持。使用name属性,按名称注入 对象生命周期(作用范围)注解
@Scope 生命周期注解,取值singleton(默认值,单实例)和prototype(多例) 初始化方法和销毁方法注解(了解)
@PostConstruct 相当于init-method
@PreDestroy 相当于destroy-method
举例
// 默认当前类名就是ID名称,首字母小写
@Component(value = "c")
// @Controller
// @Service(value = "c")
// @Repository(value = "c")
// @Scope(value = "singleton") // 默认值,单例的
// @Scope(value = "prototype") // 多例的
public class Car {
// 注解注入值,属性set方法是可以省略不写的。
// 只有一个属性,属性的名称是value,value是可以省略不写的
@Value("别克")
private String cname;
@Value(value = "500000")
private Double money;
// 也不用提供set方法
// 按类型自动装配的注解,和id名称没有关系
@Autowired
// 按id的名称注入,Qualifier不能单独使用,需要Autowired一起使用。
// @Qualifier(value = "person")
// @Resource Java提供的注解,按名称注入对象,属性名称是name
// @Resource(name = "person")
private Person person;
/*** Car对象创建完成后,调用init方法进行初始化操作 */
@PostConstruct
public void init() {
System.out.println("init...");
}
}
@Component(value = "person")
public class Person {
@Value("小明")
private String pname;
@Override
public String toString() {
return "Person{" + "pname='" + pname + '\'' + '}';
}
}
//测试(包含加载配置文件)
public class Demo {
@Test
public void run1() {
// 工厂
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");
// 获取对象
Car car = (Car) ac.getBean("c");
System.out.println(car);
}
}
3.IoC纯注解方式(编写配置类)+加载配置类
需要编写配置类,替换掉applicationContext.xml配置文件
@Bean注解 只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到IOC容器中
@Configuration // 声明配置类2
public class SpringConfig2 {
}
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "cn.demo")
// 引入新的配置类2
@Import(value = {SpringConfig2.class})
public class SpringConfig {
/**
* 创建连接池对象,返回对象,把该方法创建后的对象存入到连接池中,使用@Bean注解解决
<!‐‐配置连接池对象‐‐>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///mydb" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
*
* @return
*/
@Bean(name = "dataSource")
public DataSource createDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///mydb");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
}
并加载配置类
// 方法一:创建工厂,加载配置类 SpringConfig.class
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
// 获取到对象
Customer customer = (Customer) ac.getBean("customer");
//方法二:Spring纯注解整合Junit注解方式
@RunWith(SpringJUnit4ClassRunner.class)
// 加载配置类
@ContextConfiguration(classes = SpringConfig.class)
public class Demo {
// 按类型自动注入对象
@Autowired
private Customer customer;
/**
* 测试
*/
@Test
public void run1(){
customer.save();
}
}