在Spring4的版本中,除了要引入基本的开发包外,还需要引入一个aop包。
在src目录下创建applicationContext.xml
使用注解开发,需要引入一个context约束。
<?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: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"> <!-- bean definitions here --> </beans>UserDaoImpl.java
package com.nikehu.spring.demo1; import org.springframework.stereotype.Component; /** * 用户Dao实现类 * @author 猪猪 * */ @Component("userDao")//相当于<bean id="userDao" class="com.nikehu.spring.demo1.UserDaoImpl"/> public class UserDaoImpl implements UserDao { public void save() { System.out.println("DAO中保存用户的方法执行了"); } }使用注解方式可以没有set()方法,
如果属性有set()方法,属性注入的注解就加在set()方法上,如果没有set()方法,属性注入的注解就加在属性上。 package com.nikehu.spring.demo1; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 用户Dao实现类 * @author 猪猪 * */ @Component("userDao")//相当于<bean id="userDao" class="com.nikehu.spring.demo1.UserDaoImpl"/> public class UserDaoImpl implements UserDao { private String name; @Value("zhangsan") public void setName(String name) { this.name = name; } public void save() { System.out.println("DAO中保存用户"+name+"的方法执行了"); } } package com.nikehu.spring.demo1; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 用户Dao实现类 * @author 猪猪 * */ @Component("userDao")//相当于<bean id="userDao" class="com.nikehu.spring.demo1.UserDaoImpl"/> public class UserDaoImpl implements UserDao { @Value("zhangsan") private String name; public void save() { System.out.println("DAO中保存用户"+name+"的方法执行了"); } }xml和注解整合开发
xml用于配置Bean,可以看到我们将哪些类交给了Spring管理。
注解用于属性注入,使得类很干净,set方法也可以没有。
package com.nikehu.spring.demo3; import javax.annotation.Resource; public class ProductService { @Resource(name="productDao") private ProductDao productDao; @Resource(name="orderDao") private OrderDao orderDao; public void save(){ System.out.println("productService的save方法执行了。。。"); productDao.save(); orderDao.save(); } } package com.nikehu.spring.demo3; public class ProductDao { public void save(){ System.out.println("productDao的save方法执行了。。。"); } } package com.nikehu.spring.demo3; public class OrderDao { public void save(){ System.out.println("orderDao的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" 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"> <!-- bean definitions here --> <!-- Spring 的 IoC注解入门 --> <!-- 使用IoC的注解开发,配置扫描(哪些包下的类要使用注解),扫描是为了扫描类上的注解 --> <!-- <context:component-scan base-package="com.nikehu.spring"/> --> <!-- <context:component-scan base-package="com.nikehu.spring.demo2"/> --> <!-- 在没有包扫描的情况下,使用属性注入:@Resource,@Value,@Autowired,@Qulifier --> <context:annotation-config /> <bean id="productDao" class="com.nikehu.spring.demo3.ProductDao"/> <bean id="orderDao" class="com.nikehu.spring.demo3.OrderDao"/> <bean id="productService" class="com.nikehu.spring.demo3.ProductService"/> </beans>AOP(Aspect Oriented Programming,面向切面编程)
面向切面编程,通过预编译方式和运行时期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发的一个热点,也是spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑个部分之间的耦合度降低,提高程序的可复用性,同时提高了开发效率。
对程序进行增强:在不修改源码的情况下
AOP可以进行权限校验,日志记录,性能监控,事务控制
AOP最早由AOP联盟组织提出的,制定了一套规范,Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范。
AOP思想
Spring的AOP有自己的实现方式(非常繁琐)。
AspectJ是一个AOP框架,Spring引入AspectJ作为自身的AOP开发。
Spring有两套AOP开发方式
Spring传统方式(弃用)Spring基于AspectJ的AOP开发(使用)JoinPoint(连接点):被拦截到的点(方法),Spring只支持方法类型的连接点
Pointcut(切入点):指我们要对哪些Joinpoint进行拦定义。
Advice(通知/增强):通知是指拦截到Joinpoint之后要做的事情就是通知,通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(方法层面的增强)
Introduction(引介):一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或属性。(类层面的增强)
Target(目标):代理的目标对象
Weaving(织入):指把增强应用到目标对象来创建新的代理对象的过程。
Spring采用的是动态代理织入,而AspectJ采用编译期织入和类装载期织入。
proxy(代理)一个类被AOP织入增强后,就产生一个结果代理类。
Aspect(切面):是切入点和通知的结合。
1)创建Web项目,引入jar包
引入基本开发包
引入aop开发的相关jar包
4个
引入aop的约束
<?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 definitions here --> </beans>2)编写目标类
package com.nike.spring.demo03; public interface ProductDao { public void save(); public void update(); public void find(); public void delete(); } package com.nike.spring.demo03; public class ProductDaoImpl implements ProductDao { public void save() { System.out.println("保存商品"); } public void update() { System.out.println("修改商品"); } public void find() { System.out.println("查找商品"); } public void delete() { System.out.println("删除商品"); } } <!-- 配置目标对象 --> <bean id="productDao" class="com.nike.spring.demo03.ProductDaoImpl"></bean>3)编写测试类
spring整合Junit
引入jar包:spring-test-4.2.4.RELEASE.jar
package com.nike.spring.demo03; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //固定写法 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringDemo3 { @Resource(name="productDao") private ProductDao dao; @Test public void demo01(){ dao.save(); dao.delete(); dao.find(); dao.update(); } }4)增强save()方法,编写一个切面类。
package com.nike.spring.demo03; /** * 切面类 * @author 猪猪 * */ public class MyAspectXML { public void checkPri(){ System.out.println("权限校验。。。。。。。"); } }5)配置切面类,将切面类交给spring
<bean id="myAspect" class="com.nike.spring.demo03.MyAspectXML"></bean>6)通过AOP的配置实现,然后直接运行测试类
<!-- 配置目标对象 --> <bean id="productDao" class="com.nike.spring.demo03.ProductDaoImpl"></bean> <bean id="myAspect" class="com.nike.spring.demo03.MyAspectXML"></bean> <!-- 通过AOP的配置完成对目标类产生代理 --> <aop:config> <!-- expression表达式用于配置那些类的那些方法需要进行增强 *com.nike.spring.demo03.ProductDaoImpl.save(..) *:代指任意返回值 ..:代指任意参数 --> <aop:pointcut expression="execution(* com.nike.spring.demo03.ProductDaoImpl.save(..))" id="pointcut1"/> <!-- 配置切面 ref:切面类的id --> <aop:aspect ref="myAspect"> <aop:before method="checkPri" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config>前置通知:在目标方法执行之前进行操作;可以获得切入点的信息
<aop:before method="checkPri" pointcut-ref="pointcut1"/> public void checkPri(JoinPoint point){ System.out.println(point); System.out.println("权限校验。。。。。。。"); }后置通知:在目标方法执行之后进行操作;可以获得切入点的信息,可以获取方法返回值
<!-- 后置通知 --> <aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/> /** * 后置通知 */ public void writeLog(Object result){ System.out.println("日志记录。。。。。。。"+result); }环绕通知:在目标方法执行之前和之后进行操作;可以阻止目标方法的执行
/** * 环绕通知 * 监控性能 * @param point * @return * @throws Throwable */ public Object around(ProceedingJoinPoint point) throws Throwable{ System.out.println("环绕前。。。。。。。"); Object obj = point.proceed(); System.out.println("环绕后。。。。。。。"); return obj; } <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pointcut3"/>异常抛出通知:在程序出现异常的时候进行操作;
最终通知:无论代码是否出现异常,最终通知总会执行;
引介通知:
<?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 definitions here --> <!-- 配置目标对象 --> <bean id="productDao" class="com.nike.spring.demo03.ProductDaoImpl"></bean> <bean id="myAspect" class="com.nike.spring.demo03.MyAspectXML"></bean> <!-- 通过AOP的配置完成对目标类产生代理 --> <aop:config> <!-- expression表达式用于配置那些类的那些方法需要进行增强 *com.nike.spring.demo03.ProductDaoImpl.save(..) *:代指任意返回值 ..:代指任意参数 --> <aop:pointcut expression="execution(* com.nike.spring.demo03.ProductDaoImpl.save(..))" id="pointcut1"/> <aop:pointcut expression="execution(* com.nike.spring.demo03.ProductDaoImpl.delete(..))" id="pointcut2"/> <aop:pointcut expression="execution(* com.nike.spring.demo03.ProductDaoImpl.update(..))" id="pointcut3"/> <aop:pointcut expression="execution(* com.nike.spring.demo03.ProductDaoImpl.find(..))" id="pointcut4"/> <!-- 配置切面 ref:切面类的id --> <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-throwing method="after" pointcut-ref="pointcut4"/> </aop:aspect> </aop:config> </beans> package com.nike.spring.demo03; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /** * 切面类 * @author 猪猪 * */ public class MyAspectXML { /** * 前置通知 * @param point */ public void checkPri(JoinPoint point){ System.out.println(point); System.out.println("权限校验。。。。。。。"); } /** * 后置通知 */ public void writeLog(Object result){ System.out.println("日志记录。。。。。。。"+result); } /** * 环绕通知 * 监控性能 * @param point * @return * @throws Throwable */ public Object around(ProceedingJoinPoint point) throws Throwable{ System.out.println("环绕前。。。。。。。"); Object obj = point.proceed(); System.out.println("环绕后。。。。。。。"); return obj; } /** * 异常抛出通知 */ public void afterThrowing(Throwable ex){ System.out.println("异常抛出通知。。。。。。。。"+ex.getMessage()); } /** * 最终通知:相对于finally代码块 * */ public void after(){ System.out.println("最终通知。。。。。。。。"); } } package com.nike.spring.demo03; public class ProductDaoImpl implements ProductDao { public void save() { System.out.println("保存商品"); } public void update() { System.out.println("修改商品"); } public void find() { System.out.println("查找商品"); int i = 1/0; } public String delete() { System.out.println("删除商品"); return "返回值"; } }语法格式:基于execution的函数完成
[访问修饰符] 方法返回值 包名.类名.方法名(参数)