spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)

2023-06-08,,

1、Spring的AOP编程

什么是AOP?  ----- 在软件行业AOP为Aspect Oriented Programming  也就是面向切面编程,使用AOP编程的好处就是:在不修改源代码的情况下,可以实现代码功能的增强

AOP的实现原理(掌握)

JDK的动态代理(注意JDK的动态代理只能对实现了接口的类产生代理)

/**

* Jdk的动态代理

* @author lilong

*/

public class JdkProxy implements InvocationHandler{

//要代理的对象

private CustomerDao customerDao;

public JdkProxy(CustomerDao customerDao){

this.customerDao = customerDao;

}

/**

* 生成代理对象的方法

* @return

*/

public CustomerDao createProxy(){

CustomerDao proxy = (CustomerDao) Proxy.newProxyInstance(customerDao.getClass().getClassLoader(), customerDao.getClass().getInterfaces(), this);

return proxy;

}

/**

* 增强的方法

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("权限校验...");

return method.invoke(customerDao, args);

}

}

编写测试代码:

@Test

public void test1(){

CustomerDao customerDao = new CustomerDaoImpl();

JdkProxy jdkProxy = new JdkProxy(customerDao);

CustomerDao proxy = jdkProxy.createProxy();

proxy.save();

}

第二种代理方式Cglib方式(了解或者欣赏)

注意的是:Cglib可以对没有实现接口的类产生代理,生成子类来实现功能的增强

public class CglibProxy implements MethodInterceptor{

//要代理的对象

private LinkManDao linkManDao;

public CglibProxy(LinkManDao linkManDao) {

this.linkManDao = linkManDao;

}

public LinkManDao createProxy(){

//创建Cglib核心

Enhancer enhancer = new Enhancer();

//设置父类

enhancer.setSuperclass(linkManDao.getClass());

//设置回调

enhancer.setCallback(this);

//生成代理

LinkManDao proxy = (LinkManDao) enhancer.create();

return proxy;

}

@Override

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

System.out.println("日志记录");

Object obj = methodProxy.invokeSuper(proxy, args);

return obj;

}

}

n  编写测试代码

@Test

public void test2(){

LinkManDao linkManDao = new LinkManDao();

CglibProxy cglibProxy = new CglibProxy(linkManDao);

LinkManDao proxy = cglibProxy.createProxy();

proxy.save();

}

2、Spring的AOP开发方式(xml方式)

其中相关术语的介绍

AOP开发所需要的jar介绍

n  AOP联盟的jar包:com.springsource.org.aopalliance-1.0.0.jar

n  Spring提供的AOP的jar包:spring-aop-4.2.4.RELEASE.jar

n  AspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

n  Spring整合AspectJ的jar包:spring-aspects-4.2.4.RELEASE.jar

编写接口和实现类

ProductDao接口:

public interface ProductDao {

/**

* 持久层:产品保存

*/

public void save();

}

ProductDaoImpl实现类:

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

}

配置相关类到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"

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 id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

</beans>

编写切面类

/**

* 自定义切面类

* @author kevin

*/

public class MyAspectXml {

public void checkPrivilege(){

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"

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 id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>

</beans>

进行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: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">

<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>

<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

</aop:aspect>

</aop:config>

</beans>

编写测试类

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

public class TestAOP {

@Autowired

private ProductDao productDao;

@Test

public void test1(){

productDao.save();

}

}

总结:对切入点表达式语法进行总结

语法:[修饰符] 返回类型 包名.类名.方法名(形式参数)

常见写法:

n  execution(public * *(..))                                                                                      所有的public方法

n  execution(* set(..))                                                                                               所有set开头的方法

execution(* com.xyz.service.AccountService.*(..))                              AccountService类中的所有方法

execution(* com.xyz.service.*.*(..))                                                              com.xyz.service包下所有的方法

n  execution(* com.xyz.service..*.*(..))                                                           com.xyz.service包及其子包下所有的方法

3、Spring中AOP的通知类型

1.1.1.   前置通知:在方法执行之前增强。可以获得切入点信息。

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

</aop:aspect>

</aop:config>

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

}

1.1.2.   后置通知:在方法执行完之后增强。可以获取返回值信息。

/**

* 自定义切面类

* @author kevin

*/

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

}

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

</aop:aspect>

</aop:config>

1.1.3.   环绕通知:在方法执行前后都进行增强。可以阻止方法的执行。

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

}

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

<!-- 环绕通知 -->

<aop:around method="around" pointcut-ref="pointcut3"/>

</aop:aspect>

</aop:config>

1.1.4.   异常抛出通知:当发生异常之后增强,可以获取异常信息。

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

@Override

public void find() {

System.out.println("持久层:查询");

int i = 10/0;

}

}

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知:" + ex.getMessage());

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>

<!-- 环绕通知 -->

<aop:around method="around" pointcut-ref="pointcut3"/>

<!-- 抛出异常通知 -->

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>

</aop:aspect>

</aop:config>

1.1.5.   最终通知:不管是否有异常,都会执行的

public class MyAspectXml {

public void checkPrivilege(JoinPoint point){

System.out.println("权限校验..." + point);

}

public void afterReturn(Object result){

System.out.println("后置通知:" + result);

}

public Object around(ProceedingJoinPoint joinpoint){

System.out.println("环绕前执行");

Object obj = null;

try {

obj = joinpoint.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

System.out.println("环绕后执行");

return obj;

}

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知:" + ex.getMessage());

}

public void after(){

System.out.println("最终通知");

}

}

<!-- AOP配置 -->

<aop:config>

<!-- 配置切入点 -->

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>

<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>

<!-- 配置切面 -->

<aop:aspect ref="myAspectXml">

<!-- 前置通知 -->

<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>

<!-- 后置通知 -->

<aop:after-returning method="afterReturn" 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>

注意:最终通知和后置通知的区别:最终通知,不管异常与否,都执行;而后置通知在异常时不执行。

4、Spring的AOP注解

4.1. 创建工程,引入jar包,创建核心配置文件

<?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"

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/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="cn.itcast"></context:component-scan>

<!-- 开启自动代理注解 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

4.2. 创建接口和实现类

public interface ProductDao {

/**

* 持久层:产品保存

*/

public void save();

public int delete();

public void update();

public void find();

}

@Repository("productDao")

public class ProductDaoImpl implements ProductDao {

@Override

public void save() {

System.out.println("持久层:产品保存...");

}

public int delete(){

System.out.println("持久层:产品删除...");

return 100;

}

@Override

public void update() {

System.out.println("持久层:产品更新");

}

@Override

public void find() {

System.out.println("持久层:查询");

}

}

4.3. 编写切面类

@Component("myAspectAnnotation")

@Aspect

public class MyAspect {

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

}

提示:此处的切面类可以不取id.

5、Spring的AOP 中注解通知

5.1. 前置通知

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

5.2. 后置通知

@Aspect

public class MyAspect {

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")

public void afterReturning(Object result){

System.out.println("后置通知:" + result);

}

}

5.3. 环绕通知

@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")

public Object after(ProceedingJoinPoint joinpoint) throws Throwable{

System.out.println("环绕通知前增强");

Object obj = joinpoint.proceed();

System.out.println("环绕通知后增强");

return obj;

}

5.4. 异常通知

@AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知");

}

5.5. 最终通知

@After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

public void after(){

System.out.println("最终通知");

}

5.6. PointCut注解(了解)

作用:用于定义切入点表达式的一个注解。

@Component("myAspectAnnotation")

@Aspect

public class MyAspect {

/**

* 前置通知

* @param joinPoint

*/

@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")

public void checkPrivilege(JoinPoint joinPoint){

System.out.println("权限校验..." + joinPoint.toString());

}

@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")

public void afterReturning(Object result){

System.out.println("后置通知:" + result);

}

@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")

public Object aroung(ProceedingJoinPoint joinpoint) throws Throwable{

System.out.println("环绕通知前增强");

Object obj = joinpoint.proceed();

System.out.println("环绕通知后增强");

return obj;

}

// @AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")

@AfterThrowing(value="MyAspect.pointcut()",throwing="ex")

public void afterThrowing(Exception ex){

System.out.println("抛出异常通知");

}

// @After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

@After("MyAspect.pointcut()")

public void after(){

System.out.println("最终通知");

}

@Pointcut("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")

public void pointcut(){

}

}

spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)的相关教程结束。

《spring框架总结(03)重点介绍(Spring框架的第二种核心掌握).doc》

下载本文的Word格式文档,以方便收藏与打印。