Spring基本功能(AOP)
普通java程序开发流程
- 将spring.jar和commons-loggings.jar导入到工程中
- 创建类和方法
- 在src目录下创建applicationContext.xml文件
- 添加scheme
- 创建工厂进行调用
<?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-2.5.xsd">
<bean id="helloWorld" class="com.cai.spring.HelloWorld"></bean>
</beans>
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld=(HelloWorld) context.getBean("helloWorld");
helloWorld.hello();
Spring IOC
Spring的控制反转:把对象的创建、初始化、销毁等工作交给spring容器管理。有spring控制对象的生命周期
静态工厂方法
<!--调用HelloWorldFactory的getInstance方法创建对象,必须声明为static-->
<bean id="helloWorld2"
class="com.cai.spring.HelloWorldFactory"
factory-method="getInstance"></bean>
public HelloWorldFactory{
public static HelloWorld getInstance(){
return new HelloWorld();
}
}
//启动spring容器
ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
//根据id把spring容器中的bean提取出来了
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld2");
helloWorld.hello();
实例工厂方法
<bean id="helloWorldFactory" class="com.cai.spring.HelloWorldFactory2"></bean>
<!--
factory-bean是一个工厂bean
factory-method是一个工厂方法
-->
<bean id="helloWorld3"
factory-bean="helloWorldFactory"
factory-method="getInstance"></bean>
public HelloWorldFactory{
public HelloWorld getInstance(){
return new HelloWorld();
}
}
//启动spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld3");
helloWorld.hello();
spring容器启动流程
- 启动容器,创建容器中的对象
- 给属性装配值
- 调用init方法
- 调用业务逻辑方法
- 关闭容器时,执行destroy方法
别名
id名要和alias标签中name名对应。
在创建对象时,除了使用id名,还可以使用alias进行创建
<bean id="helloWorld" class="com.cai.spring.HelloWorld"></bean>
<alias name="helloWorld" alias="aaa" />
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld = (HelloWorld)context.getBean("aaa");
helloWorld.hello();
对象创建时间
默认情况下启动spring容器时创建对象,如果配置文件书写错误,在启动时就可以发现
启动懒加载后在getBean时创建对象
<bean id="helloWorld" class="com.cai.spring.HelloWorld" lazy-init="true"></bean>
对象单例
默认情况下,对象为单例。
将scope设置为prototype变为多例,此时在getBean时才创建对象
<bean id="helloWorld" class="com.cai.spring.HelloWorld" scope="prototype"></bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
System.out.println(helloWorld);
HelloWorld helloWorld1 = (HelloWorld)context.getBean("helloWorld");
System.out.println(helloWorld1);
init和destroy
- 在类中创建init方法和destroy方法
- 对象不能是多例的
- 在bean标签中声明init-method和destroy-method属性
- init方法在构造函数之后调用,destroy在容器调用close方法之前执行。
<bean id="helloWorld" class="com.cai.spring.HelloWorld" init-method="init" destroy-method="destroy"></bean>
DI
DI依赖注入
给属性赋值:set/get方法,构造函数
属性注入
属性注入使用 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 子节点指定属性值
public class Student {
public void say(){
System.out.println("student");
}
}
public class Person {
private Long pid;
private String name;
private Student student;
private List lists;
private Set sets;
private Map map;
private Properties properties;
private Object[] objects;
// getter,setter
}
<bean id="person" class="com.itheima12.spring.di.xml.setter.Person">
<!--
property就是一个bean的属性
name就是用来描述属性的名称
value就是值,如果是一般类型(基本类型和String)
-->
<property name="pid" value="1"></property>
<property name="name" value="狗蛋"></property>
<!--
spring容器内部创建的student对象给Person的student对象赋值了
-->
<property name="student">
<ref bean="student"/>
</property>
<property name="lists">
<list>
<value>list1</value>
<value>list2</value>
<ref bean="student"/>
</list>
</property>
<property name="sets">
<set>
<value>set1</value>
<value>set2</value>
<ref bean="student"/>
</set>
</property>
<property name="map">
<map>
<entry key="m1">
<value>map1</value>
</entry>
<entry key="m2">
<ref bean="student"/>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">prop1</prop>
<prop key="p2">prop2</prop>
</props>
</property>
<property name="objects">
<list>
<value>obj1</value>
<ref bean="student"/>
</list>
</property>
</bean>
<bean id="student" class="com.itheima12.spring.di.xml.setter.Student"></bean>
构造方法注入
<bean id="person" class="com.itheima12.spring.di.xml.constructor.Person">
<!--
constructor-arg指的是构造器中的参数
index 角标 从0开始
value 如果一般类型,用value赋值
ref 引用类型赋值
-->
<constructor-arg index="0" value="asdfsafd"></constructor-arg>
<constructor-arg index="1" ref="student"></constructor-arg>
</bean>
<bean id="student" class="com.itheima12.spring.di.xml.constructor.Student"></bean>
spring容器的继承
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Person{}
<!--
在父类中进行赋值,子类通过parent属性继承父类的内容
-->
<bean id="person" class="com.itheima12.spring.extend.Person">
<property name="name" value="aaa"></property>
</bean>
<!--
parent 实现了spring容器内部的继承关系
-->
<bean id="student" class="com.itheima12.spring.extend.Student" parent="person"></bean>
<!--
因为java的继承机制,子类继承了父类的setXxx方法,所以子类可以利用setXxx方法注入值
-->
<bean id="person2" class="com.itheima12.spring.extend.Person">
</bean>
<bean id="student2" class="com.itheima12.spring.extend.Student">
<property name="name" value="bbb"></property>
</bean>
public void testExtends(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student)context.getBean("student2");
System.out.println(student.getName());
}
spring容器的注解
- 当启动spring容器的时候,创建两个对象
- 当spring容器解析到
<context:annotation-config></context:annotation-config>
spring容器会在spring容器管理的bean的范围内查找这些类的属性上面是否加了@ Resource注解 - spring解析@Resource注解的name属性
如果name属性为”“:
说明该注解根本没有写name属性,spring容器会得到该注解所在的属性的名称和spring容器中的id做匹配,如果匹配成功,则赋值
如果匹配不成功,则按照类型进行匹配 - 如果name属性的值不为”“:
则按照name属性的值和spring的id做匹配,如果匹配成功,则赋值,不成功,则报错
public class Person {
@Resource(name="student")
// @Autowired //按照类型进行匹配
// @Qualifier("student")
private Student student;
public Student getStudent() {
return student;
}
}
public class Student {
public void say(){
System.out.println("student");
}
}
<bean id="person" class="com.itheima12.spring.di.annotation.Person"></bean>
<bean id="student" class="com.itheima12.spring.di.annotation.Student"></bean>
<!--
启动依赖注入的注解解析器
-->
<context:annotation-config></context:annotation-config>
类扫描注解
不需要再写bean标签
- 启动spring容器,spring容器解析配置文件
- 当解析到component-scan标签时,就会在上面指定的包及子包中扫描所有的类,看哪些类上面有@ Component注解
- 如果有该注解,则放入spring容器中
- 按照@ Resource注解的规则进行赋值
@Component("person")
public class Person {
@Resource(name="student")
private Student student;
public Student getStudent() {
return student;
}
}
@Component("student")
public class Student {
public void say(){
System.out.println("student");
}
}
<!--
component:把一个类放入到spring容器中,该类就是一个component
在base-package指定的包及子包下扫描所有的类
-->
<context:component-scan base-package="com.itheima12.spring.scan">
</context:component-scan>