一. IOC 和 DI
IOC : 控制反转,将对象的创建权反转给了 Spring。
DI : 依赖注入,前提是必须要有 IOC 的环境,Spring 管理这个类的时候将类的依赖的属性注入(设置)进来。
二. 工厂类
// 1. 加载类路径 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save(); // 2. 加载磁盘中的 文件路径 ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:/Users/Administrator/Desktop/applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save();
三. Bean 的作用范围配置 (xml 文件中)
1. scope : Bean 的作用范围。
! - singleton : 默认,Spring 会采用单例模式创建这个对象。
! - prototype : 多例模式。(Struts2 和 Spring 整合时会用到)
- request : 应用在 Web 项目中,Spring 创建这个类以后,将这个类存入到 request 范围中。
- session : 应用在 Web 项目中,Spring 创建这个类以后,将这个类存入到 session 范围中。
- globalsession : 应用在 Web 项目中,必须在 porlet 环境下使用,如果没有这个环境,相对于 session。
四. Spring 的属性注入方式(xml)
1. 构造方法
// 构造方法 (需要提供构造器)
<!-- 1. 构造方法 --> <bean id="shop" class="com.q.spring.demo2.ShopDao"> <constructor-arg name="name" value="apple" /> <constructor-arg name="price" value="100" /> </bean>
@Test public void demo1(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); ShopDao shopDao = (ShopDao) applicationContext.getBean("shop"); System.out.println(shopDao); }
2. set 方式的属性注入
<!-- 2. set 方法 --> <bean id="shop2" class="com.q.spring.demo2.ShopDao2"> <property name="name" value="pear" /> <property name="price" value="22" /> </bean> <!-- 2. set 方法 (p名称空间属性注入) --> <bean id="shop2" class="com.q.spring.demo2.ShopDao2" p:name="q" p:price="2222"></bean> <!-- 2. set 方法 (SpEL 属性注入) --> <bean id="shop2" class="com.q.spring.demo2.ShopDao2"> <property name="name" value="#{'q1'}"></property> <property name="price" value="#{111}"></property> </bean>
// set 方式的属性注入(需要提供 set 方法) @Test public void demo2(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); ShopDao2 shopDao = (ShopDao2) applicationContext.getBean("shop2"); System.out.println(shopDao); }
3. set 方法注入对象类型 (属性中依赖类)
<!-- 3. set 方法注入对象类型的属性 --> <bean id="person" class="com.q.spring.demo2.Person"> <property name="name" value="q" /> <property name="shopDao2" ref="shop2" /> </bean> <!-- 3. set 方法注入对象类型的属性 (p名称空间属性注入) --> <bean id="person" class="com.q.spring.demo2.Person" p:name="q1" p:shopDao2-ref="shop2"></bean> <!-- 3. set 方法注入对象类型的属性 (SpEL 属性注入) --> <bean id="person" class="com.q.spring.demo2.Person"> <property name="name" value="#{'q1'}"></property> <property name="shopDao2" value="#{shop2}"></property> </bean>
// set 方法注入对象类型(需要提供 set 方法) @Test public void demo3(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) applicationContext.getBean("person"); System.out.println(person); }
4. p名称空间属性注入
<bean id="person" class="com.q.spring.demo2.Person" p:name="q1" p:shopDao2-ref="shop2"></bean>
5. SpEL 属性注入 (Spring 3.0 之后)
<bean id="shop2" class="com.q.spring.demo2.ShopDao2"> <property name="name" value="#{'q1'}"></property> <property name="price" value="#{111}"></property> </bean>
6. 集合类型的注入 ( arrs list set map )
private String[] arrs; private List<String> list; private Set<String> set; private Map<String, String> map;
<bean id="typealls" class="com.q.spring.demo2.typeAlls"> <!-- 数组类型 --> <property name="arrs"> <list> <value>a</value> <value>b</value> <value>c</value> </list> </property> <!-- list集合 --> <property name="list"> <list> <value>a1</value> <value>b1</value> <value>c1</value> </list> </property> <!-- set集合 --> <property name="set"> <set> <value>a1</value> <value>b1</value> <value>c1</value> </set> </property> <!-- map 集合 --> <property name="map"> <map> <entry key="b2" value="b2" /> <entry key="b2" value="b2" /> <entry key="b2" value="b2" /> </map> </property> </bean>
五. 分模块开发的配置
1. 直接在一个xml文件中导入
<import resource="applicationContext.xml" />
2. 在创建 ClassPathXmlApplicationContext 时可传多个参数路径
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml1","applicationContext.xml2");
六. Spring 的 IOC 注解开发
1. 引入约束: 使用注解开发引入 Context 约束
<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"> </beans>
2. 开启 Spring 的组件扫描
<!-- 配置组件扫描(哪些包下的类使用IOC注解) --> <context:component-scan base-package="包路径"></context:component-scan>
3. 在类上添加注解
- @Component : 组件
- 装饰一个类,将这个类交给 Spring 管理。
- 这个注解有三个衍生注解: - @Controller : web 层
- @Service : service 层
- @Repository : dao 层
import org.springframework.stereotype.Component; // value 可省略: @Component("shopDao") @Component(value = "userDao") // 相当于在 <bean id="userDao" class="com.q.spring.demo2.userDemo2" /> public class userDemo2 implements UserDao { public void save(){ } }
4. 注解方式设置属性值
注解方式:使用注解方式,可以没有 set 方法。
- 属性如果有 set 方法,需要将属性注入的注解加到 set 方法上。
// 如: @Value("添加注解") public void setName(String name){ this.name = name; }
- 属性如果没有 set 方法,需要将属性注入的注解添加到属性上。
// 如: @Value("添加注解") private String name;
5. 属性注入的注解
# 普通属性:
@Value : 设置普通属性的值
# 对象类型属性:
@Autowired : 设置对象类型的属性值。但是按照类型完成属性注入(按照类名的一致)。
- 可以通过 @Qualifier 和 @Autowired 配合使用来修改为按照名称属性注入。
@Resource : 完成对象类型的属性注入,按照名称完成属性注入。 (常用)。
6. Bean 的其他注解
# 生命周期相关注解:
@PostConstruct : 初始化方法
@PreDestroy : 销毁方法
# Bean 作用范围的注解:
@scope : 作用范围
参数:
- singleton : 默认单例
- prototype : 多例
七. Spring 的 AOP 的 XML 开发
1. applocationContext.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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置目标对象 :被增强的对象 --> <bean id="productDao" class="com.q.spring.demo1.ProductDaoImpl" /> <!-- 将切面类交给 Spring 管理 --> <bean id="myAspect" class="com.q.spring.demo1.MyAspectXml" /> <aop:config> <!-- 通过AOP的配置完成对目标类产生代理 --> <aop:pointcut expression="execution(* com.q.spring.demo1.ProductDaoImpl.save(..))" id="pointcut1" /> <aop:pointcut expression="execution(* com.q.spring.demo1.ProductDaoImpl.delete(..))" id="pointcut2" /> <aop:pointcut expression="execution(* com.q.spring.demo1.ProductDaoImpl.update(..))" id="pointcut3" /> <aop:pointcut expression="execution(* com.q.spring.demo1.ProductDaoImpl.find(..))" id="pointcut4" /> <!-- 配置切面 --> <aop:aspect ref="myAspect"> <!-- 前置通知:获得切入点信息 --> <aop:before method="checkPri" pointcut-ref="pointcut1" /> <!-- 后置通知 --> <aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result" /> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pointcut3" /> <!-- 异常抛出通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex" /> <!-- 最终通知 --> <aop:after method="after" pointcut-ref="pointcut4" /> </aop:aspect> </aop:config> </beans>
2. ProductDao.java 接口文件
package com.q.spring.demo1; public interface ProductDao { public void save(); public void update(); public String delete(); public void find(); }
3. ProductDaoImpl.java DAO文件
package com.q.spring.demo1; public class ProductDaoImpl implements ProductDao { @Override public void save() { System.out.println("save"); } @Override public void update() { System.out.println("update"); } @Override public String delete() { System.out.println("delete"); return "Delete!!!"; } @Override public void find() { System.out.println("find"); // int i = 1/0; } }
4. MyAspectXML.java
package com.q.spring.demo1; // 切面类 import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyAspectXml { // 前置通知 public void checkPri(JoinPoint joinpoint){ System.out.println("权限校验 "+ joinpoint); } // 后置通知 public void writeLog(Object result){ System.out.println("日志记录 "+ result); } // 环绕通知 : 性能监控 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("环绕前通知..."); Object obj = joinPoint.proceed(); System.out.println("环绕后通知..."); return obj; } // 异常抛出通知 public void afterThrowing(Throwable ex){ System.out.println("异常抛出通知..."+ ex.getMessage()); } // 最终通知:类似于 finally public void after(){ System.out.println("最终通知..."); } }
5. 测试文件
package com.q.spring.demo1; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringDemo1 { @Resource(name="productDao") private ProductDao productDao; @Test public void demo1(){ productDao.save(); productDao.update(); productDao.delete(); productDao.find(); } }
八. Srping 的 AOP 注解
1. applocationContext.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" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 在配置文件中开启注解的AOP开发 --> <aop:aspectj-autoproxy /> <!-- 配置目标类 --> <bean id="orderDao" class="com.q.spring.demo1.OrderDao" /> <!-- 配置切面类 --> <bean id="myAspect" class="com.q.spring.demo1.MyAspectAnno" /> </beans>
2. OrderDao.java 文件
package com.q.spring.demo1; public class OrderDao { public void save(){ System.out.println("save..."); } public void update(){ System.out.println("update..."); } public String delete(){ System.out.println("delete..."); return "Delete!!!"; } public void find(){ System.out.println("find..."); // int i = 1/0; } }
3. MyAspectAnno.java 文件
package com.q.spring.demo1; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect public class MyAspectAnno { // 前置通知 // execution(* com.q.spring.demo1.OrderDao.save(..)) @Before(value = "MyAspectAnno.pointcut1()") public void befor(){ System.out.println("前置增强"); } // 后置通知 @AfterReturning(value = "MyAspectAnno.pointcut3()", returning = "result") public void afterReturning(Object result){ System.out.println("后置增强 "+ result); } // 环绕通知 @Around(value = "MyAspectAnno.pointcut2()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("环绕前增强"); Object obj = joinPoint.proceed(); System.out.println("环绕后增强"); return obj; } // 异常抛出通知 @AfterThrowing(value = "MyAspectAnno.pointcut4()", throwing = "e") public void afterThrowing(Throwable e){ System.out.println("异常抛出增强: "+e); } // 最终通知 @After(value = "MyAspectAnno.pointcut4()") public void afterThrowing(){ System.out.println("最终增强"); } // 切入点注解 @Pointcut(value = "execution(* com.q.spring.demo1.OrderDao.save(..))") private void pointcut1(){} @Pointcut(value = "execution(* com.q.spring.demo1.OrderDao.update(..))") private void pointcut2(){} @Pointcut(value = "execution(* com.q.spring.demo1.OrderDao.delete(..))") private void pointcut3(){} @Pointcut(value = "execution(* com.q.spring.demo1.OrderDao.find(..))") private void pointcut4(){} }
4. SpringDemo1.java 文件
package com.q.spring.demo1; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringDemo1 { @Resource(name = "orderDao") private OrderDao orderDao; @Test public void demo1(){ orderDao.save(); orderDao.update(); orderDao.delete(); orderDao.find(); } }