Spring的核心有两个,分别为Ioc(反转控制,new对象都依靠IoC容器来new ,IoC也可称为DI:依赖注入,类似与组合编程思想,达到调用者和被调用者完全解耦)和 AOP切面编程。
导入jar(4个核心+1个依赖),如图 2-1所示:
服务类接口
public interface UserService { void addUser(); } |
服务类实现
public class UserServiceImpl implements UserService{
@Override public void addUser() { System.out.println("add user");
}
} |
Spring配置有两种方式,一种是用xml,另一种是properties。
Spring配置文件名称一般为applicationContext.xml,位置一般放在src下
Spring配置文件如下:
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="userServiceID" class="com.baidu.ioc.UserServiceImpl">bean> beans> |
配置文件位置如图:
编写测试类:IOCTest.java
public class IOCTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/ioc/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser(); } } |
了解SpringDI的实现原理
is a :是一个,继承。 has a:有一个,成员变量,依赖。 class B { private A 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 创建dao实例:BookDao bookDao = new BookDaoImple() -->IoC 将dao设置给service:bookService.setBookDao(bookDao); -->DI |
数据库层接口
public interface UserDao { void save(); } |
数据库层实现类
public void save() { System.out.println("save user"); } |
服务层接口
public interface UserService { void addUser(); } |
服务层实现类
public class UserServiceImpl implements UserService{ //依赖注入DI的依赖 private UserDao userDao;
@Override public void addUser() { System.out.println("处理用户"); userDao.save();
} //依赖注入DI的注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; } } |
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="userServiceID" class="com.baidu.di.UserServiceImpl">
<property name="userDao" ref="userDaoId">property> bean>
<bean id="userDaoId" class="com.baidu.di.UserDaoImpl">bean> beans> |
测试类与IOC测试差不多
public class DITest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/di/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser(); } } |
测试结果
要配置的bean必须实现默认构造方法
工厂类:
public class MyFactory { public static UserService createUserService(){ return new UserServiceImpl(); } }
|
配置
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="userServiceId" class="com.baidu.staticfac.MyFactory" factory-method="createUserService">bean> beans> |
测试
public class SFacTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/staticfac/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser(); }
} |
如果你的jdk是1.8而你的spring为3.2在运行这个实例时会报错如图
解决方法:spring4.0 对应 jdk 1.8; spring3.2 对应 jdk1.7
我采用的解决把spring换成4.0版本,我的jdk是1.8的,配置如图:
重新运行如图:
必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。
非静态工厂类
public class MyFactory { //实例工厂方式 提供非静态方法获得实例 public UserService createUserService(){ return new UserServiceImpl(); } } |
配置
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="userServiceId" factory-bean="userServiceFacId" factory-method="createUserService">bean>
<bean id="userServiceFacId" class="com.baidu.factory.MyFactory">bean> beans> |
测试:如果jdk与spring不匹配会出错,具体解决方案参见4.1.2 章节
普通bean:之前操作的都是普通bean。
FactoryBean:是一个特殊的bean,具有工厂生成对象能力,只能生成特定的对象。bean必须使用 FactoryBean接口,此接口提供方法 getObject() 用于获得特定bean。
FB fb = new FB();
return fb.getObject();
常用的类别有
singleton 单例,默认值。
prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。
配置方法:
|
目标方法执行前后执行后,将进行初始化或销毁。
|
目标类:
UserServiceImpl
/** * 常用于需要初始化,用完要销毁的bean * @author Kuang * */ public class UserServiceImpl implements UserService{
@Override public void addUser() { System.out.println("add user"); } public void init(){ System.out.println("初始化"); }
public void destory(){ System.out.println("销毁的方法"); } } |
配置
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="userServiceID" class="com.baidu.lifecycle.UserServiceImpl" init-method="init" destroy-method="destory">bean>
beans> |
测试:
测试类
public class CyceleTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/lifecycle/applicationContext.xml"; //创建 applicationContext ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser();
//销毁方法要执行,applicationContext对象必须执行close方法 applicationContext.close(); } } |
测试结果:
针对Bean的初始化方法,也就是上文通过
BeanPostProcessor接口详解
spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。
模拟
A a =new A(); a = B.before(a) --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。 a.init(); a = B.after(a); a.addUser(); //生成代理对象,目的在目标方法前后执行(例如:开启事务、提交事务) a.destroy() |
MyBeanProcessor类
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之前生成代理"); System.out.println(beanName); //后期可以根据beanName经行分别处理 return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之后生成代理"); System.out.println(beanName); return bean; } } |
配置
测试截图:
依赖注入方式:手动装配 和 自动装配
手动装配:一般进行配置信息都采用手动
基于xml装配:构造方法、setter方法
基于注解装配:
自动装配:struts和spring 整合可以自动装配
byType:按类型装配
byName:按名称装配
constructor构造装配,
auto: 不确定装配。
编程
public class Student { private String name; private Integer age; //如果使用整形不能用int,而是用java.lang.Integer,否则在注入时会报错 private String sex;
public Student(String name, Integer age) { super(); this.name = name; this.age = age; }
public Student(Integer age, String sex) { super(); this.age = age; this.sex = sex; }
@Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]"; }
} |
出现的错误如下图:
配置
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="studentId" class="com.baidu.xml.constructor.Student"> <constructor-arg index="0" type="java.lang.String" value="kuang">constructor-arg> <constructor-arg index="1" type="java.lang.Integer" value="10">constructor-arg> bean> beans> |
测试结果
目标类,对上一节的类进行改变,如图:
配置
测试结果
配置
<bean id="collDataId" class="com.itheima.f_xml.e_coll.CollData" > <property name="arrayData"> <array> <value>DSvalue> <value>DZDvalue> <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> set> property>
<property name="mapData"> <map> <entry key="jack" value="杰克">entry> <entry> <key><value>rosevalue>key> <value>肉丝value> entry> map> property>
<property name="propsData"> <props> <prop key="高富帅">嫐prop> <prop key="白富美">嬲prop> <prop key="男屌丝">挊prop> props> property> bean> |
注解:就是一个类,使用@注解名称开发中:使用注解 取代 xml配置文件。
1. @Component取代
@Component("id") 取代
2.web开发,提供3个@Component注解衍生注解(功能一样)取代
@Repository :dao层
@Service:service层
@Controller:web层
3.依赖注入 ,给私有字段设置,也可以给setter方法设置
普通值:@Value("")
引用值:
方式1:按照【类型】注入
@Autowired
方式2:按照【名称】注入1
@Autowired
@Qualifier("名称")
方式3:按照【名称】注入2
@Resource("名称")
4.生命周期
初始化:@PostConstruct
销毁:@PreDestroy
5.作用域
@Scope("prototype") 多例
Spring的核心有两个,分别为Ioc(反转控制,new对象都依靠IoC容器来new ,IoC也可称为DI:依赖注入,类似与组合编程思想,达到调用者和被调用者完全解耦)和 AOP切面编程。
导入jar(4个核心+1个依赖),如图 2-1所示:
服务类接口
public interface UserService { void addUser(); } |
服务类实现
public class UserServiceImpl implements UserService{
@Override public void addUser() { System.out.println("add user");
}
} |
Spring配置有两种方式,一种是用xml,另一种是properties。
Spring配置文件名称一般为applicationContext.xml,位置一般放在src下
Spring配置文件如下:
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="userServiceID" class="com.baidu.ioc.UserServiceImpl">bean> beans> |
配置文件位置如图:
编写测试类:IOCTest.java
public class IOCTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/ioc/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser(); } } |
了解SpringDI的实现原理
is a :是一个,继承。 has a:有一个,成员变量,依赖。 class B { private A 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 创建dao实例:BookDao bookDao = new BookDaoImple() -->IoC 将dao设置给service:bookService.setBookDao(bookDao); -->DI |
数据库层接口
public interface UserDao { void save(); } |
数据库层实现类
public void save() { System.out.println("save user"); } |
服务层接口
public interface UserService { void addUser(); } |
服务层实现类
public class UserServiceImpl implements UserService{ //依赖注入DI的依赖 private UserDao userDao;
@Override public void addUser() { System.out.println("处理用户"); userDao.save();
} //依赖注入DI的注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; } } |
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="userServiceID" class="com.baidu.di.UserServiceImpl">
<property name="userDao" ref="userDaoId">property> bean>
<bean id="userDaoId" class="com.baidu.di.UserDaoImpl">bean> beans> |
测试类与IOC测试差不多
public class DITest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/di/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser(); } } |
测试结果
要配置的bean必须实现默认构造方法
工厂类:
public class MyFactory { public static UserService createUserService(){ return new UserServiceImpl(); } }
|
配置
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="userServiceId" class="com.baidu.staticfac.MyFactory" factory-method="createUserService">bean> beans> |
测试
public class SFacTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/staticfac/applicationContext.xml"; //创建 applicationContext ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser(); }
} |
如果你的jdk是1.8而你的spring为3.2在运行这个实例时会报错如图
解决方法:spring4.0 对应 jdk 1.8; spring3.2 对应 jdk1.7
我采用的解决把spring换成4.0版本,我的jdk是1.8的,配置如图:
重新运行如图:
必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。
非静态工厂类
public class MyFactory { //实例工厂方式 提供非静态方法获得实例 public UserService createUserService(){ return new UserServiceImpl(); } } |
配置
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="userServiceId" factory-bean="userServiceFacId" factory-method="createUserService">bean>
<bean id="userServiceFacId" class="com.baidu.factory.MyFactory">bean> beans> |
测试:如果jdk与spring不匹配会出错,具体解决方案参见4.1.2 章节
普通bean:之前操作的都是普通bean。
FactoryBean:是一个特殊的bean,具有工厂生成对象能力,只能生成特定的对象。bean必须使用 FactoryBean接口,此接口提供方法 getObject() 用于获得特定bean。
FB fb = new FB();
return fb.getObject();
常用的类别有
singleton 单例,默认值。
prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。
配置方法:
|
目标方法执行前后执行后,将进行初始化或销毁。
|
目标类:
UserServiceImpl
/** * 常用于需要初始化,用完要销毁的bean * @author Kuang * */ public class UserServiceImpl implements UserService{
@Override public void addUser() { System.out.println("add user"); } public void init(){ System.out.println("初始化"); }
public void destory(){ System.out.println("销毁的方法"); } } |
配置
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="userServiceID" class="com.baidu.lifecycle.UserServiceImpl" init-method="init" destroy-method="destory">bean>
beans> |
测试:
测试类
public class CyceleTest { @Test public void test(){ //配置文件相对路径 String xmlPath = "com/baidu/lifecycle/applicationContext.xml"; //创建 applicationContext ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //从spring容器获得实现类对象(不用自己new,Spring容器帮我们做了),spring容器根据配置文件配置的 UserService userService = (UserService) applicationContext.getBean("userServiceID");
userService.addUser();
//销毁方法要执行,applicationContext对象必须执行close方法 applicationContext.close(); } } |
测试结果:
针对Bean的初始化方法,也就是上文通过
BeanPostProcessor接口详解
spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。
模拟
A a =new A(); a = B.before(a) --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。 a.init(); a = B.after(a); a.addUser(); //生成代理对象,目的在目标方法前后执行(例如:开启事务、提交事务) a.destroy() |
MyBeanProcessor类
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之前生成代理"); System.out.println(beanName); //后期可以根据beanName经行分别处理 return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之后生成代理"); System.out.println(beanName); return bean; } } |
配置
测试截图:
依赖注入方式:手动装配 和 自动装配
手动装配:一般进行配置信息都采用手动
基于xml装配:构造方法、setter方法
基于注解装配:
自动装配:struts和spring 整合可以自动装配
byType:按类型装配
byName:按名称装配
constructor构造装配,
auto: 不确定装配。
编程
public class Student { private String name; private Integer age; //如果使用整形不能用int,而是用java.lang.Integer,否则在注入时会报错 private String sex;
public Student(String name, Integer age) { super(); this.name = name; this.age = age; }
public Student(Integer age, String sex) { super(); this.age = age; this.sex = sex; }
@Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]"; }
} |
出现的错误如下图:
配置
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="studentId" class="com.baidu.xml.constructor.Student"> <constructor-arg index="0" type="java.lang.String" value="kuang">constructor-arg> <constructor-arg index="1" type="java.lang.Integer" value="10">constructor-arg> bean> beans> |
测试结果
目标类,对上一节的类进行改变,如图:
配置
测试结果
配置
<bean id="collDataId" class="com.itheima.f_xml.e_coll.CollData" > <property name="arrayData"> <array> <value>DSvalue> <value>DZDvalue> <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> set> property>
<property name="mapData"> <map> <entry key="jack" value="杰克">entry> <entry> <key><value>rosevalue>key> <value>肉丝value> entry> map> property>
<property name="propsData"> <props> <prop key="高富帅">嫐prop> <prop key="白富美">嬲prop> <prop key="男屌丝">挊prop> props> property> bean> |
注解:就是一个类,使用@注解名称开发中:使用注解 取代 xml配置文件。
1. @Component取代
@Component("id") 取代
2.web开发,提供3个@Component注解衍生注解(功能一样)取代
@Repository :dao层
@Service:service层
@Controller:web层
3.依赖注入 ,给私有字段设置,也可以给setter方法设置
普通值:@Value("")
引用值:
方式1:按照【类型】注入
@Autowired
方式2:按照【名称】注入1
@Autowired
@Qualifier("名称")
方式3:按照【名称】注入2
@Resource("名称")
4.生命周期
初始化:@PostConstruct
销毁:@PreDestroy
5.作用域
@Scope("prototype") 多例
测试
错误截图
解决方案
下载并导入 spring-aop-4.0.0.RELEASE.jar (或其他适合版本)
下载地址:http://www.everycoding.com/maven2/org/springframework/spring-aop.html
正确测试结果:
测试
错误截图
解决方案
下载并导入 spring-aop-4.0.0.RELEASE.jar (或其他适合版本)
下载地址:http://www.everycoding.com/maven2/org/springframework/spring-aop.html
正确测试结果: