Spring框架的代理与AOP、AspectJ

  • Spring学习总结二
    • 0、在理解什么是AOP之前的一些话
    • 1、什么是AOP
    • 2、AOP的重要概念
    • 3、代理模式
      • 3.1、静态代理
      • 3.2、动态代理
        • 3.2.1、创建UserService接口
        • 3.2.2、创建UserServiceImp类
        • 3.2.3、创建MyAspect方面类
        • 3.2.4、动态代理UserService的工具类
        • 3.2.5、测试
    • 4、cglib代理
      • 4.1、导jar包
      • 4.2、创建接口
      • 4.3、创建实现类
      • 4.4、创建方面类
      • 4.5、用cglib的工具类来生成目标类
      • 4.6、测试
    • 5、使用spring.xml配置实现动态代理
      • 5.1、导jar包
      • 5.2、创建接口
      • 5.3、创建目标类
      • 5.4、创建方面类
      • 5.5、配置spring.xml
      • 5.6、测试
    • 6、使用spring.xml实现AOP编程
      • 6.1、在上面一个例子的基础上加一个包
      • 6.2、创建接口
      • 6.3、创建实现类
      • 6.4、创建方面类
      • 6.5、配置spring.xml
      • 6.6、测试
    • 7、使用AspectJ配置spring.xml实现AOP编程
      • 7.1、导包
      • 7.2、创建接口
      • 7.3、创建实现类
      • 7.4、创建MyAspect类
      • 7.5、编写spring.xml
      • 7.6、测试
    • 8、使用注解的AspectJ
      • 8.1、导包
      • 8.2、创建接口
      • 8.3、创建实现类
      • 8.4、创建MyAcpect
      • 8.5、编写spring.xml
      • 8.6、测试

Spring学习总结二

今天的主要内容就是AOP:

  1. 什么是AOP
  2. AOP的重要概念
  3. 代理模式
  4. cglib代理
  5. 使用spring.xml配置实现动态代理
  6. 使用spring.xml实现AOP编程
  7. 使用AspectJ配置spring.xml实现AOP编程
  8. 使用注解的AspectJ

0、在理解什么是AOP之前的一些话

下面1、2两点都是我百度上抄的,说实话,我是不太能说出这么精准的术语来。

AOP,通俗来说就是在执行特定的方法前或者后,去做"某些事情"(比如:转账前需要将设置事务,转账"成功"后需要提交事务)

我们将尺度放大!有一些业务经常需要换一些功能。而我们不想再去改项目的硬编码,从而有了AOP,或者是说,我想通过xml配置来动态的增加以及减少一些功能,这时候AOP就可以大显身手了

如何学好AOP?

先训练,再看概念!理清楚思路,你将对AOP的概念读上几遍。

1、什么是AOP

AOP: (Aspect Oriented Programming) 面向切面编程。是目前软件开发中的一个热点,也是Spring框架中容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等

AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。 而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

举个简单的例子,对于“雇员”这样一个业务实体进行封装,自然是OOP的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。

同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOP对一个动作进行封装,则有点不伦不类。 换而言之,OOP面向名词领域,AOP面向动词领域。

总之,AOP可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

2、AOP的重要概念

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。然而殊途同归,实现AOP的技术特性却是相同的,分别为:

  1. join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。
  2. point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。
  3. advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。
  4. aspect(方面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。
  5. introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。

上述的技术特性组成了基本的AOP技术,大多数AOP工具均实现了这些技术。它们也可以是研究AOP技术的基本术语

3、代理模式

说到代理模式,我们就需要说到下面两点:

  1. 静态代理
  2. 动态代理

3.1、静态代理

这里就不写静态代理的代码了。自己百度去看,主要的是以下3个点:

  1. 目标类
  2. 代理类
  3. 上面两个类继承同一个接口

3.2、动态代理

需要做的事情就5步:

  1. 创建接口,名为UserService
  2. 创建一个实现UserService接口的实现类,名为UserServiceImp
  3. 创建一个方面类,名为MyAspect
  4. 使用JDK自带的动态代理类来生成UserService的动态代理,这个类是一个工具类,名为MyBeanFactory
  5. 测试

3.2.1、创建UserService接口

package com.csa.service;
public interface UserService {public void addUser();public void updateUser();public void deleteUser();
}

3.2.2、创建UserServiceImp类

package com.csa.service.Imp;
import com.csa.service.UserService;
public class UserServiceImp implements UserService{@Overridepublic void addUser() {// TODO Auto-generated method stubSystem.out.println("add User to ...");}@Overridepublic void updateUser() {// TODO Auto-generated method stubSystem.out.println("update User to ...");}@Overridepublic void deleteUser() {// TODO Auto-generated method stubSystem.out.println("delete User to ...");}}

3.2.3、创建MyAspect方面类

package com.csa.aspect;
public class MyAspect {public void before(){System.out.println("之前");}public void after(){System.out.println("之后");}
}

3.2.4、动态代理UserService的工具类

动态代理步骤:

  1. 创建一个实现InvocationHandler接口的类,它必须实现invoke()方法
  2. 创建被代理的类及接口创建被代理的类及接口
  3. 调用Proxy的静态方法,创建一个代理类调用Proxy的静态方法,创建一个代理类
  4. 通过代理调用方法

想了解更多的可以看这篇代理模式深入理解

package com.csa.factory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.csa.aspect.MyAspect;
import com.csa.service.UserService;
import com.csa.service.Imp.UserServiceImp;
public class MyBeanFactory {public static UserService createService() {// 1. 目标类UserService userService = new UserServiceImp();// 2. 切面类MyAspect myAspect = new MyAspect();// 3. 代理类UserService proxyService = (UserService) Proxy.newProxyInstance(MyBeanFactory.class.getClassLoader(),userService.getClass().getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubmyAspect.before();Object obj = method.invoke(userService,args);myAspect.after();return obj;}});return proxyService;}
}

3.2.5、测试

package com.csa.Test;
import org.junit.Test;
import com.csa.factory.MyBeanFactory;
import com.csa.service.UserService;
public class TestJDK {@Testpublic void demo(){UserService userService = MyBeanFactory.createService();userService.addUser();userService.updateUser();userService.deleteUser();}}

测试结果:

4、cglib代理

分6步完成:

  1. 导jar包
  2. 创建接口,名为UserService(与上面动态代理的一样)
  3. 创建一个实现UserService接口的实现类,名为UserServiceImp(与上面动态代理的一样)
  4. 创建一个方面类,名为MyAspect(与上面动态代理的一样)
  5. 使用cglib的工具类来生成UserService的动态代理,这个类是一个工具类,名为MyBeanFactory
  6. 测试

4.1、导jar包

spring各个版本官方下载地址

4.2、创建接口

(与上面动态代理的一样)

4.3、创建实现类

(与上面动态代理的一样)

4.4、创建方面类

(与上面动态代理的一样)

4.5、用cglib的工具类来生成目标类

package com.csa.factory;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import com.csa.aspect.MyAspect;
import com.csa.service.UserService;
import com.csa.service.Imp.UserServiceImp;public class MyBeanFactory {public static UserService createService() {// 1. 目标类UserService userService = new UserServiceImp();// 2. 切面类MyAspect myAspect = new MyAspect();// 3. 代理类// 3.1  核心类Enhancer enhancer = new Enhancer();// 3.2   确定父类enhancer.setSuperclass(userService.getClass());// 3.3   设置回调函数enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {// TODO Auto-generated method stubmyAspect.before();Object obj = method.invoke(userService, args);myAspect.after();return obj;}});UserServiceImp proxyService = (UserServiceImp) enhancer.create();return proxyService;}
}

4.6、测试

package com.csa.Test;
import org.junit.Test;
import com.csa.factory.MyBeanFactory;
import com.csa.service.UserService;
public class TestCGLIB {@Testpublic void demo(){UserService userService = MyBeanFactory.createService();userService.addUser();userService.updateUser();userService.deleteUser();}}

测试结果:

5、使用spring.xml配置实现动态代理

分下面6个步骤:

  1. 导jar包
  2. 创建接口,名为UserService(与动态代理的一样)
  3. 创建一个实现UserService接口的实现类,名为UserServiceImp(与动态代理的一样)
  4. 创建一个方面类,名为MyAspect
  5. 创建spring.xml并配置
  6. 测试

5.1、导jar包

Spring下载地址
commons logging下载地址
aopalliance下载地址

最后导入的包是如下(简称为:4+1、aop联盟):

5.2、创建接口

(与动态代理的一样)

5.3、创建目标类

(与动态代理的一样)

5.4、创建方面类

需要做两件事:

  1. 继承某个接口。
  2. 实现接口的方法。

所有的接口:

  1. 前置通知:接口MethodBeforeAdvice
  2. 后置通知:接口AfterReturningAdvice
  3. 环绕通知:接口MethodInterceptor(掌握)
  4. 异常通知:接口ThrowsAdvice
  5. 带返回值的后置通知:接口AfterReturningAdvice
package com.csa.aspect;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyAspect implements MethodInterceptor{/*** 很明显,这是一个环绕通知*/@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {System.out.println("之前");Object obj = mi.proceed();System.out.println("之后");return obj;}}

5.5、配置spring.xml

注意,我的spring.xml在src的config包下:

spring.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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 1 创建目标类 --><bean id="userServiceId" class="com.csa.service.Imp.UserServiceImp"></bean><!-- 2 创建切面类 --><bean id="myAspectId" class="com.csa.aspect.MyAspect"></bean><!-- 3 创建代理类 * 使用工厂bean FactoryBean ,底层调用 getObject() 返回特殊bean* ProxyFactoryBean 用于创建代理工厂bean,生成特殊代理对象interfaces : 确定接口通过<array>可以设置多个值只有一个值时,value=""target : 确定目标类interceptorNames : 通知 切面类的名称,类型String[],如果设置一个值 value=""optimize :强制使用cglib<property name="optimize" value="true"></property>底层机制如果目标类有接口,采用jdk动态代理如果没有接口,采用cglib 字节码增强如果声明 optimize = true ,无论是否有接口,都采用cglib--><bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="interfaces" value="com.csa.service.UserService"></property><property name="target" ref="userServiceId"></property><property name="interceptorNames" value="myAspectId"></property></bean></beans>

5.6、测试

package com.csa.Test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.service.UserService;public class TestAOP {@Testpublic void demo(){String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("proxyServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}}

测试结果:

6、使用spring.xml实现AOP编程

下面的几个步骤:

  1. 在上面一个例子的基础上加一个包
  2. 创建接口,名为UserService(与动态代理的一样)
  3. 创建一个实现UserService接口的实现类,名为UserServiceImp(与动态代理的一样)
  4. 创建一个方面类,名为MyAspect(与上一个例子的一样)
  5. 创建spring.xml并配置
  6. 测试

6.1、在上面一个例子的基础上加一个包

AspectJ Weaver包下载地址

最后的包是:

6.2、创建接口

(与动态代理的一样)

6.3、创建实现类

(与动态代理的一样)

6.4、创建方面类

(与上一个例子的一样)

6.5、配置spring.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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 1. 目标类 --><bean id="userServiceId" class="com.csa.service.Imp.UserServiceImp"></bean><!-- 2. 切面类 --><bean id="myAspectId" class="com.csa.aspect.MyAspect"></bean><!-- 3. aop编程 --><!-- 简单来说呢,就是连接点:是"所有需要增加某一个特定功能的方法集合"织入:就是将某个有特定处理功能的类,加到"连接点"!--><aop:config proxy-target-class="true"><!-- 这里涉及得到一个表达式的问题,我给个超链接,自己看吧 --><!-- 下面是一个连接点,这里的表达式就是为了告诉spring,哪些方法需要被加以处理! --><aop:pointcut expression="execution(* com.csa.service..*(..))" id="myPointcut"/><!-- 下面就是我们的切面类,切面类会被"织入"到连接点 --><aop:advisor advice-ref="myAspectId" pointcut-ref="myPointcut"/></aop:config></beans>

6.6、测试

package com.csa.Test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.service.UserService;public class TestAOP {@Testpublic void demo(){String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}}

测试结果:

7、使用AspectJ配置spring.xml实现AOP编程

分6步:

  1. 导包
  2. 创建接口
  3. 创建实现类
  4. 创建MyAspect
  5. 编写spring.xml
  6. 测试

7.1、导包

在上一个例子的基础上导入下面这个包!在spring的压缩包下可以找到!

7.2、创建接口

不变

7.3、创建实现类

要加一个除零异常

package com.csa.service.Imp;
import com.csa.service.UserService;
public class UserServiceImp implements UserService {@Overridepublic void addUser() {System.out.println("addUser to ...");}@Overridepublic void updateUser() {int i = 1/0;System.out.println("updateUser to ...");}@Overridepublic void deleteUser() {System.out.println("deleteUser to ...");}}

7.4、创建MyAspect类

以下是所有AOP的通知了!

package com.csa.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {/*** 前置* * @param joinPoint*            连接点*/public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知: " + joinPoint.getSignature().getName());}/*** 后置* * @param joinPoint*            连接点*/public void myAfter(JoinPoint joinPoint) {System.out.println("后置通知: " + joinPoint.getSignature().getName());}/*** 环绕通知* * @param proceedingJoinPoint*            连接点* @return 返回被代理方法的具体返回值* @throws Throwable*             proceedingJoinPoint.proceed()方法执行抛出的异常*/public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("前:" + proceedingJoinPoint.getSignature().getName());Object obj = proceedingJoinPoint.proceed();System.out.println("后:" + proceedingJoinPoint.getSignature().getName());return obj;}/*** 异常通知* * @param joinPoint*            连接点* @param e*            被代理方法执行出现异常*/public void myThrowing(JoinPoint joinPoint, Throwable e) {System.out.println("异常通知:" + joinPoint.getSignature().getName() + "\r\n异常类型:" + e.getMessage());}/*** 后置通知* * @param joinPoint*            连接点* @param ret被代理方法的具体返回值*/public void myReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知:" + joinPoint.getSignature().getName() + "\r\n返回值:" + ret);}}

7.5、编写spring.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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 目标类 --><bean id="userServiceId" class="com.csa.service.Imp.UserServiceImp"></bean><!-- 切面类 --><bean id="myAspectId" class="com.csa.aspect.MyAspect"></bean><aop:config><!-- 注意是在这个标签下,直接引用了某个切面类 --><aop:aspect ref="myAspectId"><!-- 在这个标签的体中间写"通知"和"被通知的方法集合" --><!-- 连接点--><aop:pointcut expression="execution(* com.csa.service..*(..) )" id="myPointcut"/><!-- 前置通知<aop:before method="myBefore" pointcut-ref="myPointcut"/>--><!-- 后置通知<aop:after method="myAfter" pointcut-ref="myPointcut"/>--><!-- 环绕通知<aop:around method="myAround" pointcut-ref="myPointcut"/>--><!--异常通知--><aop:after-throwing method="myThrowing" pointcut-ref="myPointcut" throwing="e"/><!--后置通知<aop:after-returning method="myReturning" pointcut-ref="myPointcut" returning="ret"/>--><!-- jdk1.8 最好别使用 spring3.*.*系列 --></aop:aspect></aop:config>
</beans>

7.6、测试

package com.csa.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.csa.service.UserService;
public class TestAspectJ {@Testpublic void demo() {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}
}

测试结果:

8、使用注解的AspectJ

分6个步骤:

  1. 导包
  2. 创建接口
  3. 创建实现类
  4. 创建MyAcpect
  5. 编写spring.xml
  6. 测试

8.1、导包

与上一个例子的包一样,没有改变!

8.2、创建接口

没变

8.3、创建实现类

上一个AspectJ的例子一样!

8.4、创建MyAcpect

package com.csa.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component
@Aspect
public class MyAspect {/*** 连接点*/@Pointcut(value="execution(* com.csa.service..*(..) )")private void myPointcut() {}/*** 前置* * @param joinPoint*            连接点*/@Before(value="myPointcut()")public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知: " + joinPoint.getSignature().getName());}/*** 后置* * @param joinPoint*            连接点*/@After(value="myPointcut()")public void myAfter(JoinPoint joinPoint) {System.out.println("后置通知: " + joinPoint.getSignature().getName());}/*** 环绕通知* * @param proceedingJoinPoint*            连接点* @return 返回被代理方法的具体返回值* @throws Throwable*             proceedingJoinPoint.proceed()方法执行抛出的异常*/@Around(value="myPointcut()")public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("前:" + proceedingJoinPoint.getSignature().getName());Object obj = proceedingJoinPoint.proceed();System.out.println("后:" + proceedingJoinPoint.getSignature().getName());return obj;}/*** 异常通知* * @param joinPoint*            连接点* @param e*            被代理方法执行出现异常*/@AfterThrowing(value="myPointcut()",throwing="e")public void myThrowing(JoinPoint joinPoint, Throwable e) {System.out.println("异常通知:" + joinPoint.getSignature().getName() + "\r\n异常类型:" + e.getMessage());}/*** 后置通知* * @param joinPoint*            连接点* @param ret被代理方法的具体返回值*/@AfterReturning(value="myPointcut()",returning="ret")public void myReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知:" + joinPoint.getSignature().getName() + "\r\n返回值:" + ret);}}

8.5、编写spring.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: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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 扫描 注解类 --><context:component-scan base-package="com.csa"></context:component-scan><!-- 确定 aop注解生效 --><aop:aspectj-autoproxy ></aop:aspectj-autoproxy></beans>

8.6、测试

package com.csa.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.csa.service.UserService;
public class TestAspectJ {@Testpublic void demo() {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}
}

测试结果:

Spring学习总结二相关推荐

  1. Spring学习(二)Spring IoC 和 DI 简介

    本文借鉴:Spring学习(特此感谢!) 一.IOC(控制反转) 定义:反转控制 (Inversion Of Control)的缩写,即创建对象的反转控制. 正向控制:若要使用某个对象,需要自己去负责 ...

  2. Spring 学习之 二----Spring创建对象的三种方式

    最近在系统的学习Spring,现在就Spring的一些知识进行总结. 我们知道Spring是一个开放源代码的设计层面的框架,他主要解决的是业务逻辑层与其他各层之间松耦合的问题. Spring 有三个核 ...

  3. Spring学习系列(二) 自动化装配Bean

    一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组 ...

  4. Spring学习(二)—— 对象创建方式及依赖注入

    文章目录 对象创建方式 配置 依赖注入 构造器注入 Set方式注入 拓展方式注入 对象创建方式 默认使用无参构造器创建 当我们需要使用有参构造器时,有以下几种方式: 1.下标赋值 <!--第一种 ...

  5. Java学习笔记-Day64 Spring 框架(二)

    Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...

  6. Spring Boot 框架学习笔记(二)(配置文件与数据注入 yaml基本语法 JSR303数据验证 多环境切换 )

    Spring Boot 框架学习笔记(二) 六.appliaction.properties配置与数据注入 6.1 `@Value`注解 测试注入数据 读取输入流 6.2 读取配置文件数据注入 单文件 ...

  7. Spring5学习(二):Spring 配置、依赖注入

    Spring5学习(二) 5.Spring 配置 5.1 别名 5.2 Bean的配置 5.3 import 6.依赖注入 6.1 构造器注入 6.2 Set注入 6.3 其他注入 6.4 bean的 ...

  8. 我的Spring学习记录(二)

    本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...

  9. Spring学习(九)Spring 和数据库编程【了解】

    本文借鉴:Spring学习,Spring框架总结 一.传统 JDBC 回顾 用一个大佬的demo来简单看一下 /*** 使用jdbc,根据id查询单个Student的信息*/ public class ...

最新文章

  1. ubuntu上面安装nodejs,npm,bower,grunt,yeoman
  2. qualcomm memory dump 抓取方法
  3. POJ 1833 排列【STL/next_permutation】
  4. 正则表达式的一些探索(偏JavaScript)
  5. 快速搭建react项目骨架(按需加载、redux、axios、项目级目录等等)
  6. MailBee电子邮件发送接收pop3/IMAP4/SMTP套件MailBee Objects下载
  7. 首席架构师眼里的架构本质
  8. 网络编程实战之在线电子词典
  9. 单面打印机双面打印———python pdf拆分重排
  10. 打开计算机硬盘是个磁盘图标 不显示大小,硬盘图标显示异常的解决办法
  11. Microsoft server2008的sql server身份验证出现18456错误
  12. 教你如何在2023年办好水土保持资质
  13. 用于 Power 体系结构的汇编语言
  14. 我的世界服务器npc怎么修改,我的世界NPCmod教程如何设置任务NPC
  15. 网易云音乐解除灰色小工具 - 资源
  16. Android 11 微信友盟分享报错 分享异常 Android 11及以上系统的手机需要使用FileProvider方式分享
  17. 如何免费将OFD转成PDF
  18. jira--研发管理-敏捷。
  19. Chromedriver安装教程(简洁版)
  20. Spider学习笔记(十二):视频下载插件ffmpeg的使用操作介绍

热门文章

  1. Golang的for range遍历
  2. 启动celery后执行任务报错:django.core.exceptions.ImproperlyConfigured
  3. 通过Playbook部署LAMP(5)
  4. 手动将经典 VM 从 VHD 迁移到新的 ARM 托管磁盘 VM
  5. 三层架构与四大天王之——查
  6. 软件工程的瀑布, 大泥球, 教堂,集市,和银弹
  7. [算法 笔记]字符串表达式计算(简易版)
  8. chapter 15 运算符详解
  9. Codeblocks 安装
  10. Arraylist gossip