轻量级
的Java 开发框架,由Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性
而创建的。该框架的主要优势之一就是其分层架构
,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性
、可测试性
和松耦合
的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)
和面向切面(AOP)
。简单来说,Spring是一个分层的
JavaSE/EE full-stack(一站式)
轻量级开源框架。spring-MVC
spring
jdbcTemplate
–> spring-data
Spring就是一个大工厂(容器)
,可以将所有对象创建和依赖关系维护,交给Spring管理。Spring工厂就是用于生成Bean。
4 + 1:4个核心jar包(beans、core、context、expression)+ 1个依赖jar包(com.springsource.org.apache.commons.logging-1.1.1.jar)
项目中的显示:
Spring核心开发包简介:
private IUserDao dao = new IUserDaoImpl();
IoC 控制反转(Inverse of Control)
UserService.java
public interface UserService {
void addUser();
}
UserServiceImpl.java
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("a_ioc add user");
}
}
beans.xml
<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="userServiceId" class="com.itheima.a_ioc.UserServiceImpl">bean>
beans>
TestIoC.java
public class TestIoC {
@Test
public void demo01() {
// 之前开发,自己手写new出对象
UserService userService = new UserServiceImpl();
userService.addUser();
}
@Test
public void demo02() {
// 现在从spring容器中获得对象实例
// 1 、获得容器
String xmlPath = "com/itheima/a_ioc/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
}
}
class B {
private A a; // B类依赖A类,B类使用A类。
}
依赖:一个对象需要使用另一个对象。
注入:通过setter方法进行另一个对象实例设置。
class BookServiceImpl {
// 之前开发:接口 = 实现类(service和dao耦合了,写死了,知道具体的实现类是谁,那么我的具体实现类变化,那么这行代码也得跟着变)
// private BookDao bookDao = new BookDaoImpl();
// spring之后(解耦:service实现类使用了dao的接口,这样就不知道具体的实现类是谁了)
private BookDao bookDao;
setter方法
}
模拟spring执行过程
创建service实例:BookService bookService = new BookServiceImpl(); => IoC <bean>
创建dao实例:BookDao bookDao = new BookDaoImple(); => IoC
将dao设置给service:bookService.setBookDao(bookDao); => DI <property>
BookDao.java
public interface BookDao {
void save();
}
BookDaoImpl.java
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("b_di add book");
}
}
BookService.java
public interface BookService {
void addBook();
}
BookServiceImpl.java
public class BookServiceImpl implements BookService {
// 方式1:之前,接口 = 实现类
// private BookDao bookDao = new BookDaoImpl();
// 方式2:现在,接口 + setter
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void addBook() {
this.bookDao.save();
}
}
<?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">
<!--
模拟spring执行过程
创建service实例:BookService bookService = new BookServiceImpl(); => IoC <bean>
创建dao实例:BookDao bookDao = new BookDaoImple(); => IoC
将dao实例设置给service实例:bookService.setBookDao(bookDao); => DI <property>
<property> 用于进行属性注入
name : Bean的属性名称,通过setter方法获得
setBookDao => BookDao => bookDao
ref :另一个Bean的id值的引用
-->
<!-- 创建service实例 -->
<bean id="bookServiceId" class="com.itheima.b_di.BookServiceImpl">
<!-- 将dao实例设置给service实例 -->
<property name="bookDao" ref="bookDaoId"></property> <!-- 用于进行属性注入 -->
</bean>
<!-- 创建dao实例 -->
<bean id="bookDaoId" class="com.itheima.b_di.BookDaoImpl"></bean>
</beans>
public class TestDI {
@Test
public void demo01() {
// 之前开发,自己手写new出对象
// BookService bookService = new BookServiceImpl();
// bookService.addBook();
}
@Test
public void demo02() {
// 现在从spring容器中获得对象实例
// 1 、获得容器
String xmlPath = "com/itheima/b_di/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
BookService bookService = (BookService) applicationContext.getBean("bookServiceId");
bookService.addBook();
}
}
工厂
,用于生成任意Bean。 采取延迟加载,第一次调用getBean(); 时才会初始化Bean。(即实例化对象)
采取非延时加载,当配置文件被加载时,就进行对象的实例化。
示例代码如下:
public class TestDI {
@Test
public void demo01() {
// 之前开发,自己手写new出对象
// BookService bookService = new BookServiceImpl();
// bookService.addBook();
}
@Test
public void demo02() {
// 现在从spring容器中获得对象实例,使用的是ApplicationContext
// 1 、获得容器
String xmlPath = "com/itheima/b_di/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); // 采取非延时加载,当配置文件被加载时,就进行对象的实例化。
// 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
BookService bookService = (BookService) applicationContext.getBean("bookServiceId");
bookService.addBook();
}
@Test
public void demo03() {
// 现在从spring容器中获得对象实例,使用的是BeanFactory,里面需要一个Resource,该Resource又是一个接口,需要找它的实现类ClassPathResource
// 1 、获得容器
String xmlPath = "com/itheima/b_di/beans.xml";
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(xmlPath));
// 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
BookService bookService = (BookService) beanFactory.getBean("bookServiceId"); // 采取延迟加载,第一次调用getBean(); 时才会初始化Bean(即实例化对象)。
bookService.addBook();
}
}
默认构造方法
实例化静态工厂方法
实例化实例工厂方法
实例化格式:
<bean id="从Spring容器中获得实例时使用的" class="需要创建实例的全限定类名">bean>
例如:<bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl">bean>
示例中用到的 UserService.java 和 UserServiceImpl.java 代码同上 2.2、编写目标类 的代码,这里不再赘述!
在spring容器中进行配置:
beans.xml
<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="userServiceId" class="com.itheima.a_ioc.UserServiceImpl">bean>
beans>
测试代码:
TestIoC.java
public class TestIoC {
@Test
public void demo01() {
// 之前开发,自己手写new出对象
UserService userService = new UserServiceImpl(); // 直接手动创建实例
userService.addUser();
}
@Test
public void demo02() {
// 现在从spring容器中获得对象实例
// 1 、获得容器
String xmlPath = "com/itheima/a_ioc/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
}
}
示例中用到的 UserService.java 和 UserServiceImpl.java 代码同上 2.2、编写目标类 的代码,这里不再赘述!
格式:
<bean id="" class="工厂全限定类名" factory-method="静态方法名称">
在spring容器中进行配置:
beans.xml
<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="userServiceId" class="com.itheima.c_inject.b_static_factory.MyBeanFactory" factory-method="createService">bean>
beans>
静态工厂类代码:
public class MyBeanFactory {
/**
* 创建实例的静态工厂,所有的方法必须是静态的(static)。
*
* @return
*/
public static UserService createService() {
return new UserServiceImpl();
}
// 还有创建其他实例的静态工厂
// ......
}
测试代码:
TestStaticFactory.java
/**
* 第二种实例化Bean 的方式 :使用静态工厂方法实例化
*
*/
public class TestStaticFactory {
@Test
public void demo01() {
// 以前:使用自定义的静态实例工厂
UserService userService = MyBeanFactory.createService();
userService.addUser();
}
@Test
public void demo02() {
// 现在:使用spring 工厂:将自定义的静态工厂创建的实例交给spring管理
String xmlPath = "com/itheima/c_inject/b_static_factory/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
// UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
}
}
注意:当使用JDK版本为1.8时,运行上面的测试代码会出现一个问题: java.lang.IllegalArgumentException,
问题解决链接:使用Junit测试一个 spring静态工厂实例化bean 的例子,所有代码都没有问题,但是出现java.lang.IllegalArgumentException异常
小结:在以后的开发中,工厂类不需要我们去手写,因为别人已经写好了,我们通过编写配置文件
,把别人写好的工厂类拿来,写上要用的方法名,然后把它生产后的实例给Spring存起来,以后我们要用什么实例,跟Spring说一下,去拿就可以了。
示例中用到的 UserService.java 和 UserServiceImpl.java 代码同上 2.2、编写目标类 的代码,这里不再赘述!
在spring容器中进行配置:
beans.xml
<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="myBeanFactoryId" class="com.itheima.c_inject.c_factory.MyBeanFactory" >bean>
<bean id="userServiceId" factory-bean="myBeanFactoryId" factory-method="createService">bean>
beans>
静态工厂类代码:
public class MyBeanFactory {
/**
* 创建实例的工厂,所有方法非静态
*
* @return
*/
public UserService createService() {
return new UserServiceImpl();
}
// 还有创建其他实例的工厂
// ......
}
测试代码:
TestFactory.java
package com.itheima.c_inject.c_factory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 第三种实例化Bean 的方式 :使用实例工厂方法实例化
* */
public class TestFactory {
@Test
public void demo01() {
// 以前:使用自定义的实例工厂
// 1、创建工厂实例
MyBeanFactory myBeanFactory = new MyBeanFactory();
// 2、通过工厂实例,获得对象
UserService userService = myBeanFactory.createService();
userService.addUser();
}
@Test
public void demo02() {
// 现在:使用spring 工厂:将自定义的实例工厂创建的实例交给spring管理
String xmlPath = "com/itheima/c_inject/c_factory/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
// UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
}
}
< bean id="xxx" class="A" >
,这句代码的意思是:Spring直接创建A的实例,并返回。具有工厂生成对象能力
,但是只能生成特定的对象。 < bean id="xxx" class="FB">
,这句代码的意思是:Spring会先创建FB实例,然后调用getObject(); 方法,并返回方法的返回值。 < bean id="xxx" class="....ProxyFactoryBean">
,这句代码的意思是:获得代理对象的实例。即AOP使用。spring容器中bean元素id和name属性的区别?
< bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl">
区别二:
name : 如果Bean的名称中含有特殊字符,就需要使用name属性
例如 : < bean name="# boy" class="cn.itheima.ioc.Boy"/>
因为name属性可以相同,所以后出现Bean会覆盖之前出现的同名的Bean。
总结:项目开发的时候,强烈要求用id,因为id可以表示唯一引用。
< bean id="xxx" class="xxx" scope="xxx">
lazy-init="true"
来延迟初始化bean,这时候,只有第一次获取bean会才初始化bean。 < bean id="xxx" class="cn.itheima.UserServiceImpl" lazy-init="true">
default-lazy-init="true"
, < beans default-lazy-init="true“>
示例代码如下:
示例中用到的 UserService.java 和 UserServiceImpl.java 代码同上 2.2、编写目标类 的代码,这里不再赘述!
在spring容器中进行配置:
beans.xml
<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="userServiceId" class="com.itheima.d_scope.UserServiceImpl" scope="prototype">bean>
beans>
测试代码:
TestScope.java
public class TestScope {
@Test
public void demo01() {
// 现在:使用spring 工厂
String xmlPath = "com/itheima/d_scope/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService1 = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
UserService userService2 = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
// 默认Bean的作用域是单例,所以打印的对象的地址是一样的
// System.out.println(userService1); // com.itheima.c_inject.d_scope.UserServiceImpl@2ac273d3
// System.out.println(userService2); // com.itheima.c_inject.d_scope.UserServiceImpl@2ac273d3
// 现在在配置文件中添加scope属性,值为prototype,此时Bean的作用域变为多例了,再次打印,输出地址不一样了
System.out.println(userService1); // com.itheima.c_inject.d_scope.UserServiceImpl@66480dd7
System.out.println(userService2); // com.itheima.c_inject.d_scope.UserServiceImpl@52a86356
}
}
- instantiate bean 对象实例化。
- populate properties 封装属性。
- 如果Bean实现 BeanNameAware,则表示执行
setBeanName
。- 如果Bean实现 BeanFactoryAware 或者 ApplicationContextAware,则表示设置实例工厂(
setBeanFactory
)或者上下文对象(setApplicationContext
)。- 如果存在类实现 BeanPostProcessor(后处理Bean),则表示执行
postProcessBeforeInitialization
。- 如果Bean实现 InitializingBean,则表示执行
afterPropertiesSet
。- 调用
,则表示指定初始化方法
init
。- 如果存在类实现 BeanPostProcessor(处理Bean),则表示执行
postProcessAfterInitialization
。- 执行业务处理
- 如果Bean实现 DisposableBean,则表示执行
destroy
。- 调用
,则表示指定销毁方法
customerDestroy
。
目标方法执行前和执行后,将进行Bean的初始化或销毁。
示例:
示例代码如下:
编写目标类代码:
UserService.java
public interface UserService {
void addUser();
}
UserServiceImpl.java
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("e_lifecycle add user");
}
public void myInit() {
System.out.println("我的初始化方法");
}
public void myDestory() {
System.out.println("我的销毁方法");
}
}
编写配置文件:
beans.xml
<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="userServiceId" class="com.itheima.c_inject.e_lifecycle.UserServiceImpl"
init-method="myInit" destroy-method="myDestory">bean>
beans>
编写测试代码:
public class TestLifecycle {
@Test
public void demo01() throws Exception {
// 现在:使用spring 工厂(spring 容器)
String xmlPath = "com/itheima/c_inject/e_lifecycle/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
// 要想使我的销毁方法也执行,必须要求:
// 1.容器必须先close,我的销毁方法才会执行;
// 2.必须是单例的(spring所创建该bean的实例个数只有一个)即bean中的scope配置成默认即可。
// 因为此close方法在接口 ApplicationContext 中没有定义,而在实现类中提供了该方法,我们可以使用反射,因为反射最后执行的就是实现类中的方法。
applicationContext.getClass().getMethod("close").invoke(applicationContext);
}
}
这句代码的意思就是:把实现类提供给了spring容器。 我们来模拟这句话的意思:
before() => postProcessAfterInitialization(Object bean, String beanName)
after() => postProcessBeforeInitialization(Object bean, String beanName)
A a = new A();
a = B.before(a); // 将a的实例对象传递给后处理bean,可以什么都没做,也可以做一些事情,比如:生成jdk代理对象并返回给a,这样a就从实例对象变成代理对象了,此时的a就具有了AOP功能;再比如,如果把null返回给a,再用a去调用方法,就会出现空指针异常。
a.init();
a = B.after(a);
// 以下是AOP演示:
// 我们现在在后处理Bean 代码执行完之后,把jdk代理对象返回给a。让a在调用addUser()之前先做一些事情
// 之前要做的事情
a.addUser(); // 在目标方法的前后可以做一些事情,例如:开启事务、提交事务、性能监控(前后时间)等等
// 之后要做的事情
a.destroy();
目标类示例代码如下:
UserService.java
public interface UserService {
void addUser();
}
UserServiceImpl.java
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("e_lifecycle add user");
}
public void myInit() {
System.out.println("我的初始化方法");
}
public void myDestory() {
System.out.println("我的销毁方法");
}
}
实现类示例代码如下:
MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行了前方法:" + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("执行了后方法:" + beanName);
// 传入的参数bean是我们的目标对象,此时我们的目标对象只有一个接口,那么我们的代理对象也只有一个接口
// 生成jdk代理对象
return Proxy.newProxyInstance(
MyBeanPostProcessor.class.getClassLoader(), // 代理对象
bean.getClass().getInterfaces(), // 目标对象
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---开启事务---");
Object obj = method.invoke(bean, args); // 执行目标方法,本例中的目标方法是addUser
System.out.println("---关闭事务---");
return obj;
}
}); // 代理的处理程序
}
}
配置文件示例代码如下:
beans.xml
<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="userServiceId" class="com.itheima.e_lifecycle.UserServiceImpl"
init-method="myInit" destroy-method="myDestory">bean>
<bean class="com.itheima.e_lifecycle.MyBeanPostProcessor">bean>
beans>
测试示例代码如下:
TestLifecycle.java
public class TestLifecycle {
@Test
public void demo01() throws Exception {
// 现在:使用spring 工厂(spring 容器)
String xmlPath = "com/itheima/e_lifecycle/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();
// 要想使我的销毁方法也执行,必须要求:
// 1.容器必须先close,我的销毁方法才会执行;
// 2.必须是单例的(spring所创建该bean的实例个数只有一个)即bean中的scope配置成默认即可。
// 因为此close方法在接口 ApplicationContext 中没有定义,而在实现类中提供了该方法,我们可以使用反射,因为反射最后执行的就是实现类中的方法。
applicationContext.getClass().getMethod("close").invoke(applicationContext);
}
}
手工装配
或自动装配
。 实际应用中
建议使用手工装配
,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。Bean对象类:
public class User {
private Integer uid;
private String username;
private Integer age;
public User(Integer uid, String username) { // 构造方法一
super();
this.uid = uid;
this.username = username;
}
public User(String username, Integer age) { // 构造方法二
super();
this.username = username;
this.age = age;
}
// 省略getter 和 setter 方法
// ......
spring的配置:
<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="userId" class="com.itheima.f_xml.a_constructor.User">
<constructor-arg index="0" type="java.lang.String" value="1">constructor-arg>
<constructor-arg index="1" type="java.lang.Integer" value="2">constructor-arg>
bean>
beans>
spring的配置:
<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="personId" class="com.itheima.f_xml.b_setter.Person">
<property name="pname" value="晓艺">property>
<property name="age">
<value>26value>
property>
<property name="homeAddr" ref="homeAddrId">property>
<property name="companyAddr">
<ref bean="companyAddrId">ref>
property>
bean>
<bean id="homeAddrId" class="com.itheima.f_xml.b_setter.Address">
<property name="addr" value="山西运城">property>
<property name="tel" value="911">property>
bean>
<bean id="companyAddrId" class="com.itheima.f_xml.b_setter.Address">
<property name="addr" value="百子湾">property>
<property name="tel" value="120">property>
bean>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="personId" class="com.itheima.f_xml.c_p.Person"
p:pname="明军"
p:age="26"
p:homeAddr-ref="homeAddrId"
p:companyAddr-ref="companyAddrId">
bean>
<bean id="homeAddrId" class="com.itheima.f_xml.c_p.Address"
p:addr="河南信阳"
p:tel="119">
bean>
<bean id="companyAddrId" class="com.itheima.f_xml.c_p.Address"
p:addr="青年路"
p:tel="110">
bean>
beans>
进行统一编程,所有的内容都使用value。 格式:
示例代码如下:
spring的配置:
<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="customerId" class="com.itheima.f_xml.d_SpEL.Customer">
<property name="cname" value="#{customerId.cname?.toUpperCase()}">property>
<property name="pi" value="#{T(java.lang.Math).PI}">property>
bean>
beans>
spring的配置:
<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="collectionDataId" class="com.itheima.f_xml.e_collection.CollectionData">
<property name="arrayData">
<array>
<value>cmjvalue>
<value>lxyvalue>3
<value>明军value>
<value>晓艺value>
array>
property>
<property name="listData">
<list>
<value>琴棋书画value>
<value>撸哑铃value>
<value>花鸟鱼虫value>
<value>撸娃娃value>
list>
property>
<property name="setData">
<set>
<value>看电影value>
<value>运动value>
<value>创作value>
<value>旅行value>
set>
property>
<property name="mapData">
<map>
<entry key="bruce" value="布鲁斯">entry>
<entry>
<key><value>lucyvalue>key>
<value>露西value>
entry>
map>
property>
<property name="propsData">
<props>
<prop key="处女座">内心善良prop>
<prop key="天蝎座">宅心仁厚prop>
<prop key="缘定今生">此生不悔prop>
props>
property>
bean>
beans>
1. @Component 取代
@Component("id的值")
2. web开发中,提供3个@Component注解衍生注解(功能一样)取代
@Repository :dao层
@Service :service层
@Controller :web层
注意:SpringMVC 中推荐使用注解哦!
3. 依赖注入,给私有字段设置,也可以给setter方法设置
普通值:@Value("")
引用值:
方式1:按照【类型】注入
@Autowired
方式2:按照【类型+名称】注入1
@Autowired
@Qualifier("名称")
方式3:按照【名称】注入2
@Resource("名称")
4. 生命周期
@PostConstruct :初始化
@PreDestroy :销毁
5. 作用域
@Scope("prototype") 多例
示例代码:
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.itheima.g_annotation.a_ioc">context:component-scan>
beans>
演示:
单例、多例、初始化、销毁
UserService.java
package com.itheima.g_annotation.c_other;
public interface UserService {
void addUser();
}
UserServiceImpl.java
@Service("userServiceId") // 单例
@Scope("prototype") // 多例
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("c_other add user");
}
@PostConstruct // 初始化
public void myInit() {
System.out.println("我的初始化方法");
}
@PreDestroy // 销毁
public void myDestory() {
System.out.println("我的销毁方法");
}
}
beans.xml
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.itheima.g_annotation.c_other">context:component-scan>
beans>
测试代码:
TestOther.java
package com.itheima.g_annotation.c_other;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestOther {
@Test
public void demo01() {
// 现在:使用spring 工厂
String xmlPath = "com/itheima/g_annotation/c_other/beans.xml";
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService1 = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
UserService userService2 = applicationContext.getBean("userServiceId", UserService.class); // 这种方式底层会自动转换
// 默认Bean的作用域是单例,所以打印的对象的地址是一样的
// System.out.println(userService1); // com.itheima.c_inject.d_scope.UserServiceImpl@2ac273d3
// System.out.println(userService2); // com.itheima.c_inject.d_scope.UserServiceImpl@2ac273d3
// 现在在配置文件中添加scope属性,值为prototype,此时Bean的作用域变为多例了,再次打印,输出地址不一样了
System.out.println(userService1); // com.itheima.c_inject.d_scope.UserServiceImpl@66480dd7
System.out.println(userService2); // com.itheima.c_inject.d_scope.UserServiceImpl@52a86356
applicationContext.close();
}
}
1、导入jar包:4 + 1 --> beans/core/context/expression + commons-logging
2、编写目标类:dao 和 service
3、 Spring配置文件
IoC:
<bean id="" class="">bean>
DI:
<bean><property name="" value="" | ref="">property>bean>
实例化方式:
默认构造
静态工厂:
<bean id="" class="工厂类全限定类名" factory-method="静态方法名称">bean>
实例工厂:
<bean id="工厂的id" class="工厂类">bean>
<bean id="" factory-bean="工厂的id" factory-method="方法名称">bean>
作用域:
<bean id="" class="" scope="singleton | prototype">bean>
生命周期:
<bean id="" class="" init-method="" destroy-method="">bean>
后处理bean:实现BeanPostProcessor接口,,对容器中所有的bean都生效。
属性注入:
构造方法注入:
<bean><constructor-arg index="" type="">bean>
setter方法注入:
<bean><property name="" value="" | ref="">bean>bean>
p命名空间:简化
格式:
<bean p:属性名="普通值" p:属性名-ref="引用值">bean>
注意:使用p命名空间需要先声明命名空间。
SpEL:
<property name="" value="#{表达式}">
#{123} #{‘abc’}
#{beanId.propName?.methodName()}
#{T(类).静态方法|字段}
集合注入
数组 ...
List ...
Set ...
Map
Properties ...
4、核心api
BeanFactory,延迟实例化bean,第一次调用getBean(); 时才会初始化Bean。
ApplicationContext 一般常用,功能更强,采取非延时加载,当配置文件被加载时,就进行对象的实例化。
ClassPathXmlApplicationContext 加载classpath中的xml文件
FileSystemXmlApplicationContext 加载指定盘符的文件,ServletContext.getRealPath()
5、使后处理bean 只对一个生效
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 使后处理bean 只对一个生效
if("userServiceId".equals(beanName)) {
System.out.println("执行了前方法:" + beanName);
}
return bean;
}
6、注解
1、先配置扫描含有注解的类
2、常见的注解
@Component 组件,注入任意bean
WEB
@Controller web层
@Service service层
@Repository dao层
注入字段或setter方法
普通值:@Value
引用值:
按类型:@Autowired
按名称1:@Autowired @Qualifier("名称")
按名称2:@Resource("名称")
作用域:@Scope("prototype")
生命周期:
初始化:@PostConstruct
销毁方法:@PreDestroy
7、注解和xml混合使用
1.将所有的bean都配置xml中
<bean id="" class="">bean>
2.将所有的依赖都使用注解
@Autowired
默认不生效。为了生效,需要在xml配置:
总结:
注解1:
注解2:
1、一般情况两个注解不一起使用。
2、 “注解1”扫描含有注解(@Component 等)类,注入的注解自动生效。
“注解2”只在xml和注解(注入)混合使用时,使注入的注解生效
摘自传智播客系列课程笔记