Spring学习笔记IOC与AOP实例,Spring框架2核心

Spring框架的核心是什么?(IoC和AOP) IoC(控制反转)和AOP(面向切面编程)。我们将从传统开发的痛点出发,理解IoC如何通过"反转依赖控制权"实现解耦,AOP如何通过"横切逻辑模块化"解决重复代码问题;接着深入底层原理,解析IoC容器的Bean管理机制和AOP的动态代理实现;最后通过实战案例,展示如何在项目中灵活应用IoC和AOP提升代码质量。IoC和AOP是Spring框架的两大核心,它们并非孤立存在,而是协同工作。 阅读详情

Spring学习笔记IOC与AOP实例
Spring框架核心由两部分组成:

第一部分是反向控制(IOC),也叫依赖注入(DI);

  控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象。在以XML语言描述的配置文件中,声明web系统中哪个组件需要哪一种服务时,不是在程序中让对象和服务直接连接,具体负责连接工作的是Web容器,Spring中就是Ioc容器。

IoC的优点和缺点

 优点:因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拔(有点象USB接口和SCIS硬盘了)。

 缺点:(1)生成一个对象的步骤变复杂了(其实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3)缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。

       开发中具体实现方式:

SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式

          1.JavaBean的Setter方法注入

如图:

接口 Logic.java

package DI;

/**

  • 类Logic.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:02:35
    */
    public interface Logic {

    public String getName();

}
接口实现类 LogicImpl.java

package DI;

/**

  • 类Logiclmpl.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:03:53
    */
    public class Logiclmpl implements Logic {

    public String getName() {
    return “xiong jinlian”;
    }

} 
一个处理类 LoginAction.java(LoginAction.java 会根据使用不同的注入方法而稍有不同)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package DI;

/**

  • 类LoginAction.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:07:10
    */
    public class LoginAction {

    private Logic logic;

    /**

    • @return the logic
      */
      public Logic getLogic() {
      return logic;
      }

    /**

    • @param logic the logic to set
      */
      public void setLogic(Logic logic) {
      this.logic = logic;
      }

    public void execute() {
    String name = logic.getName();
    System.out.println("My name is " + name);
    }

}
还有一个测试类 TestMain.java(客户端测试类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package DI;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**

  • 类TestMain.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:12:19
    */
    public class TestMain {

    /**

    • @param args
      */
      public static void main(String[] args) {
      // TODO Auto-generated method st
      ApplicationContext ac = new ClassPathXmlApplicationContext(“appContext.xml”);
      LoginAction la = (LoginAction) ac.getBean(“loginAction”);
      la.execute();
      }

}
 定义了一个Logic 类型的变量 logic, 在LoginAction并没有对logic 进行实例化,而只有他对应的setter/getter方法,因为我们这里使用的是Spring的依赖注入的方式

appContext.xml

1
2
3
4
5
6
7
8
9
10
11

<?xml version="1.0"?>








 运行截图:

          2.构造方法注入

   构造方法注入,就是我们依靠LoginAction的构造方法来达到DI的目的,如下所示,添加了一个LoginAction的构造方法:

LoginAction.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package DI;

/**

  • 类LoginAction.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:07:10
    */
    public class LoginAction {

    private Logic logic;

    public LoginAction(Logic logic){
    this.logic = logic;
    }

    public void execute() {
    String name = logic.getName();
    System.out.println("My name is " + name + “构造方法注入”);
    }
    }
    appContext.xml

1
2
3
4
5
6
7
8
9
10
11

<?xml version="1.0"?>







 
使用constructor-arg来进行配置, index属性是用来表示构造方法中参数的顺序的,如果有多个参数,则按照顺序,从 0,1…来配置。其中需要注意一点:构造函数有多个参数的话,如:参数1,参数2,而参数2依赖于参数1,这种情况则要注意构造函数的顺序,必须将参数1放在参数2之前。

我们现在可以运行testMain.java了,结果跟使用Setter方法注入完全一样.

          3.接口注入

不常用到的接口注入,还是以LogicAction为例,我们对他进行了修改,如下所示:

LogicAction.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package DI;

/**

  • 类LoginAction.java的实现描述:TODO 类实现描述

  • @author jinlian.xjl 2015年7月6日 下午2:07:10
    */
    public class LoginAction {

    private Logic logic;

    public void execute() {
    try {
    // forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。
    Class clazz = Class.forName(“DI.Logiclmpl”);

         // newInstance() 创建此 Class 对象所表示的类的一个新实例。
         logic = (Logic) clazz.newInstance();
    
         String name = logic.getName();
         System.out.println("My name is " + name + "测试接口注入");
    
     } catch (Exception e) {
    
         e.printStackTrace();
     }
    

    }
    }
      appContext.xml

1
2
3
4
5
6
7
8
9

<?xml version="1.0"?>






 运行:

小结:

对于Spring的依赖注入,最重要的就是理解它们,无非就是让容器来给我们实例化那些类,我们要做的就是给容器提供这个接口,这个接口就我们的set方法或者构造函数了。

第二部分面向方面的编程(AOP).

1.Aop简介

   AOP(Aspect Oriented Programming):面向切面编程(面向方面编程),通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,提高开发效率。

   用途:

   AOP 来处理一些具有横切性质的系统性服务,如事物管理、安全检查、缓存、对象池管理(日志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理)等

  AOP 的实现原理:
   如图:AOP 实际上是由目标类的代理类实现的。AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异,AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。

 Spring 中对 AOP 的支持:

     Spring 中 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。Spring 默认使用 Java 动态代理来创建 AOP 代理, 这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring 自动会切换为使用 CGLIB 代理,也可强制使用 CGLIB。 

     AOP 编程需要程序员参与的只有三个部分:

定义普通业务组件。
定义切入点,一个切入点可能横切多个业务组件。
定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。
所以进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法。

  Spring 中 AOP 的实现:

    Spring 有如下两种选择来定义切入点和增强处理。

基于 Annotation注解的“零配置”方式:使用@Aspect、@Pointcut等 Annotation 来标注切入点和增强处理。
基于 XML 配置文件的管理方式:使用 Spring 配置文件来定义切入点和增强点。

 1). 切面(Aspect)

   官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如:AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。“切面”在ApplicationContext中<aop:aspect>来配置。

 2). 连接点(Joinpoint)

   程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者BServiceImpl.barB(String _msg, int _type)抛出异常等行为。

 3). 通知(Advice)

  “切面”对于某个“连接点”所产生的动作,例如,TestAspect中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。其中,一个“切面”可以包含多个“Advice”,例如TestAspect。Advice共有如下5种类型:

A 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。xml中在<aop:aspect>里面使用<aop:before>元素进行声明;例如,TestAspect中的doBefore方法。注解中使用@Before声明;例如,TestAnnotationAspect中的doBefore方法。

B 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。xml中在<aop:aspect>里面使用<aop:after>元素进行声明。例如,TestAspect中的doAfter方法,所以AOPTest中调用BServiceImpl.barB抛出异常时,doAfter方法仍然执行。注解中使用@After声明。

C 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。xml中在<aop:aspect>里面使用<after-returning>元素进行声明。注解中使用@AfterReturning声明;

D 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。xml中在aop:aspect里面使用aop:around元素进行声明。例如,TestAspect中的doAround方法。注解中使用@Around声明。

E 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。xml中在aop:aspect里面使用aop:after-throwing元素进行声明。例如,TestAspect中的doThrowing方法。注解中使用@AfterThrowing声明。

 通知执行顺序:前置通知→环绕通知连接点之前→连接点执行→环绕通知连接点之后→返回通知→后置通知→(如果发生异常)异常通知→后通知

4). 切入点(Pointcut)

   匹配连接点的断言,在AOP中通知和一个切入点表达式关联。例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service.*.*(..))来决定。

  ● 切入点表达式

 execution:用于匹配方法执行的连接点;

 within:用于匹配指定类型内的方法执行;

 this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;注意this中使用的表达式必须是完整类名,不支持通配符;

 target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是完整类名,不支持通配符;

 args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;参数类型列表中的参数必须是完整类名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;

  @within:用于匹配所以持有指定注解类型内的方法;注解类型也必须是完整类名;

  @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是完整类名;

  @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是完整类名;

  @annotation:用于匹配当前执行方法持有指定注解的方法;注解类型也必须是完整类名;

  bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;

  reference pointcut:表示引用其他命名切入点,只有注解风格支持,XML风格不支持。

 ● 匹配语法
  • 匹配任何数量字符;

… 匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

  • 匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
    例如:

java.lang.String 匹配String类型;

java.*.String 匹配java包下的任何“一级子包”下的String类型;如匹配java.lang.String,但不匹配java.lang.ss.String。

java…* 匹配java包及任何子包下的任何类型;如匹配java.lang.String、java.lang.annotation.Annotation。

java.lang.*ing 匹配任何java.lang包下的以ing结尾的类型;

java.lang.Number+ 匹配java.lang包下的任何Number的自类型;如匹配java.lang.Integer,也匹配java.math.BigInteger。

● 匹配种类

A 类

[plain] view plaincopy

注解 类名
注解:可选,类上持有的注解,如@Deprecated;

类名:必填,任何类的完整名称。

B 方法

[plain] view plaincopy

注解 修饰符 返回值类型 类名 方法名(参数列表) 异常列表
注解:可选,方法上持有的注解,如@Deprecated;

修饰符:可选,如public、protected;

返回值类型:必填,可以是任何类型模式;“*”表示所有类型;

类名:可选,任何类的完整名称;

方法名:必填,可以使用“*”进行模式匹配;

参数列表:“()”表示方法没有任何参数;“(…)”表示匹配接受任意个参数的方法,“(…,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法;“(java.lang.String,…)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;

异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。

C Bean

可以使用Bean的id或name进行匹配,并且可使用通配符“*”。

● 匹配逻辑运算

可以使用且(&&)、或(||)、非(!)来组合切入点表达式。由于在XML中使用“&&”需要使用转义字符“&&”来代替之,所以很不方便,因此Spring ASP 提供了and、or、not来代替&&、||、!。

● 切入点表达式示例

A execution

模式 描述
public * *(…) 任何公共方法的执行

  • cn.javass…IPointcutService.*() cn.javass包及所有子包下IPointcutService接口中的任何无参方法
  • cn.javass….(…) cn.javass包及所有子包下任何类的任何方法
  • cn.javass…IPointcutService.() cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
  • (!cn.javass…IPointcutService+).*(…) 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
  • cn.javass…IPointcutService+.*() cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
  • cn.javass…IPointcut*.test*(java.util.Date) cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;
  • cn.javass…IPointcut*.test*(…) throws IllegalArgumentException, ArrayIndexOutOfBoundsException cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
  • (cn.javass…IPointcutService+&& java.io.Serializable+).*(…) 任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
    @java.lang.Deprecated * *(…) 任何持有@java.lang.Deprecated注解的方法
    @java.lang.Deprecated @cn.javass…Secure * *(…) 任何持有@java.lang.Deprecated和@cn.javass…Secure注解的方法
    @(java.lang.Deprecated || cn.javass…Secure) * *(…) 任何持有@java.lang.Deprecated或@ cn.javass…Secure注解的方法
    (@cn.javass…Secure *) *(…) 任何返回值类型持有@cn.javass…Secure的方法
  • (@cn.javass…Secure ).(…) 任何定义方法的类型持有@cn.javass…Secure的方法
  • (@cn.javass…Secure () , @cn.javass…Secure (*)) 任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1,@Secure String str1);
  • *((@ cn.javass…Secure ))或 *(@ cn.javass…Secure *) 任何带有一个参数的方法,且该参数类型持有@ cn.javass…Secure;如public void test(Model model);且Model类上持有@Secure注解
  • *(@cn.javass…Secure (@cn.javass…Secure *) ,@ cn.javass…Secure (@cn.javass…Secure *)) 任何带有两个参数的方法,且这两个参数都被@ cn.javass…Secure标记了;且这两个参数的类型上都持有@ cn.javass…Secure;
  • (java.util.Map<cn.javass…Model, cn.javass…Model>, …) 任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass…Model, cn.javass…Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“ *(java.util.HashMap<cn.javass…Model,cn.javass…Model>, …)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配
  • *(java.util.Collection<@cn.javass…Secure *>) 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解;如public void test(Collection collection);Model类型上持有@cn.javass…Secure
    B within

模式 描述
within(cn.javass…*) cn.javass包及子包下的任何方法执行
within(cn.javass…IPointcutService+) cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
within(@cn.javass…Secure *) 持有cn.javass…Secure注解的任何类型的任何方法必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
C this

模式 描述
this(cn.javass.spring.chapter6.service.IPointcutService) 当前AOP对象实现了 IPointcutService接口的任何方法
this(cn.javass.spring.chapter6.service.IIntroductionService)
当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口

D target

模式 描述
target(cn.javass.spring.chapter6.service.IPointcutService) 当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
target(cn.javass.spring.chapter6.service.IIntroductionService) 当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法不可能是引入接口

模式 描述
args (java.io.Serializable,…) 任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的
F @within

模式 描述
@within cn.javass.spring.chapter6.Secure) 任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
G @target

模式 描述
@target (cn.javass.spring.chapter6.Secure) 任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
H @args

模式 描述
@args (cn.javass.spring.chapter6.Secure) 任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;
I @annotation

模式 描述
@annotation(cn.javass.spring.chapter6.Secure ) 当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配
J bean

模式 描述
bean(*Service)
匹配所有以Service命名(id或name)结尾的Bean

K reference pointcut

[java] view plaincopy

@Pointcut(value=“bean(*Service)”)
private void pointcut1(){}

@Pointcut(value="@args(cn.javass.spring.chapter6.Secure)")
private void pointcut2(){}

@Pointcut(value=“pointcut1()&&pointcut2()”)
private void pointcut3(){}
● 通知方法参数注入

在Spring AOP中,除了execution和bean指示符不能传递参数给通知方法,其他指示符都可以将匹配的相应参数或对象自动传递给通知方法。例如:

[java] view plaincopy

@Before(value="execution(* test()) && args(param)", argNames=“param”)
public void before1(String param) {
System.out.println("===param:" + param);
}
首先execution(
test(*))匹配任何方法名为test,且有一个任何类型的参数;

args(param)将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型,即java.lang.String;如果匹配将把该被通知参数传递给通知方法上同名参数。

其他指示符(除了execution和bean指示符)都可以使用这种方式进行参数绑定。

● 综合示例

[java] view plaincopy

@Before(value=“args(param) && target(bean) && @annotation(secure)”, argNames=“jp,param,bean,secure”)
public void before5(JoinPoint jp, String param,
IPointcutService pointcutService, Secure secure) {
……
}

除了上边介绍的普通方式,也可以对使用命名切入点自动获取参数:

[java] view plaincopy

@Pointcut(value=“args(param)”, argNames=“param”)
private void pointcut1(String param){}

@Pointcut(value="@annotation(secure)", argNames=“secure”)
private void pointcut2(Secure secure){}

@Before(value = “pointcut1(param) && pointcut2(secure)”, argNames=“param, secure”)
public void before6(JoinPoint jp, String param, Secure secure) {
……
}
5). 目标对象(Target Object)

   被一个或者多个切面所通知的对象。例如,AServcieImpl和BServiceImpl,当然在实际运行时,Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。

 6). AOP代理(AOP Proxy)

   在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,例如:AServiceImpl;反之,采用CGLIB代理,例如:BServiceImpl。强制使用CGLIB代理需要将 <aop:config>的 proxy-target-class属性设为true。



XML方式实例:

 文件目录路径如下:

 

    切面类TestAspect.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package AOP;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class TestAspect {

public void doBefore(JoinPoint jp) {
    System.out.println("Before  :" + jp.getTarget().getClass().getName() + "……" + jp.getSignature().getName());
}

public void doAfter(JoinPoint jp) {
    System.out.println("After  :" + jp.getTarget().getClass().getName() + "……" + jp.getSignature().getName());
}

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    long time = System.currentTimeMillis();
    Object retVal = pjp.proceed();
    time = System.currentTimeMillis() - time;
    System.out.println("Around  : process time:" + "……" + time + " ms");
    return retVal;
}

public void doThrowing(JoinPoint jp, Throwable ex) {
    System.out.println("Throwing  :" + jp.getTarget().getClass().getName() + "……" + jp.getSignature().getName());
    System.out.println("Throwing  : " + ex.getMessage());

}

}
  目标对象类:

          AServiceImpl.java实现接口类AService.java(实现了接口,使用jdk动态代理方式)

1
2
3
4
5
6
7
8
9
10
package AOP;

public interface AService {

public void barA();

public void fooA(String _msg);

public void mayThrow(int _type);

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package AOP;

//jdk动态代理方式
public class AServiceImpl implements AService {

public void barA() {

    System.out.println("AServiceImpl.barA()");
}

public void fooA(String _msg) {

    System.out.println("AServiceImpl.fooA(_msg:)" + _msg + ")");
}

public void mayThrow(int _type) {
    if (_type == 1) {
        throw new IllegalArgumentException("这是AServiceImpl异常测试");
    }
}

}
目标对象类:

         BServiceImpl.java(并未实现任何借口,默认cglib方式) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package AOP;

//cglib
public class BServiceImpl {

public void barB(String _msg, int _type) {
    System.out.println("BServiceImpl.barB(msg:" + _msg + ")");
    if (_type == 1) {
        throw new IllegalArgumentException("这是BServiceImpl异常测试");
    }
}

public void fooB() {
    System.out.println("BServiceImpl.fooB()");
}

}
appContext.xml文件:Spring配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

<?xml version="1.0"?>







aop:config
<aop:aspect id=“asTestAspect” ref=“testAspect”>
<aop:pointcut id=“pcService” expression=“execution(* AOP..(…))”></aop:pointcut>
<aop:before pointcut-ref=“pcService” method=“doBefore”/>
<aop:after pointcut-ref=“pcService” method=“doAfter”/>
<aop:around pointcut-ref=“pcService” method=“doAround”/>
<aop:after-throwing pointcut-ref=“pcService” method=“doThrowing” throwing=“ex”/>
</aop:aspect>
</aop:config>

  客户端测试:ClientMain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package AOP;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ClientMain {

public static void main(String[] args) {

    ApplicationContext ac = new ClassPathXmlApplicationContext("appContext.xml");
    AService aSerImpl = (AService) ac.getBean("aServiceImpl");
    aSerImpl.barA();
    System.out.println("---------------------------------------");
    aSerImpl.fooA("Client main 测试  AServiceImpl  Jdk动态代理");
    System.out.println("---------------------------------------");
    aSerImpl.mayThrow(1);

    System.out.println("*******************************************************");

    /*
     * BServiceImpl bSerImpl = (BServiceImpl) ac.getBean("bServiceImpl");
     * bSerImpl.barB("Client main 测试  BServiceImpl  cglib", 1); System.out.println("----------------------");
     * bSerImpl.fooB();
     */

}

}
  运行结果:

友情链接

Spring Aop实例 http://blog.youkuaiyun.com/wangpeng047/article/details/8560694

Spring AOP 的简单例子
Spring AOP 实现了AOP联盟(Alliance)的制定的接口规范,它基于java的代理机制实现。AOP作为Spring的核心技术之一. 更多关于Spring AOP介绍 可参考:http://oss.org.cn/ossdocs/framework/spring/zh-cn/aop.html 下面给出一个例子来简单介绍Spring AOP具体实现过程

现假设用户通过login.jsp页面输入相应的用户名和密码之后,首先Spring AOP的环绕通知验证该用户名和密码是否符合要求,若符合要求,则到数据库中查找该用户,若用户存在,将该用户相关的信息写入日志。

1.BaseLoginAdvice 类实现了 前置通知接口(MethodBeforeAdvice)、环绕通知接口(MethodInterceptor)、后置通知接口(AfterReturningAdvice) 这三个接口

BaseLoginAdvice.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.laoyangx.Aop.chapter0;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public abstract class BaseLoginAdvice implements MethodBeforeAdvice, MethodInterceptor,
AfterReturningAdvice {
/**
* @param returnValue 目标方法返回值
* @param method 目标方法
* @param args 方法参数
* @param target 目标对象
*
*/
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {

     throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
}
 
 
/**
 * @param invocation 目标对象的方法
 */
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
     
    throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
}

/**
 * @param method 将要执行的目标对象方法
 * @param args 方法的参数
 * @param target 目标对象
 */
@Override
public void before(Method method, Object[] args, Object target)
        throws Throwable {
     
    throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
}

}
2.LoginAdviceSupport 类继承 BaseLoginAdvice 类,并重写 BaseLoginAdvice 类的三个方法

LoginAdviceSupport.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.laoyangx.Aop.chapter0;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInvocation;

public class LoginAdviceSupport extends BaseLoginAdvice {

/**
 * 若在数据库中存在指定的用户,将用户登录信息写入日志文件
 * @param returnValue 目标方法返回值
 * @param method 目标方法
 * @param args 方法参数
 * @param target 目标对象
 */
@Override
public void afterReturning(Object returnValue, Method method,
        Object[] args, Object target) throws Throwable {
     
   System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:afterReturning ----------------");
   
   //将用户登录信息写入日志文件
}

/**
 * 验证用户输入是否符合要求
 * @param invocation 目标对象的方法
 */
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
     
    System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:invoke ----------------");
     
    String username=invocation.getArguments()[0].toString();
    String password=invocation.getArguments()[1].toString();
     
    //在这里进行相关的验证操作 
     
    //假设验证通过
    return invocation.proceed();
}

/**
 * 在数据库中查找指定的用户是否存在
 * @param method 将要执行的目标对象方法
 * @param args 方法的参数
 * @param target 目标对象
 */
@Override
public void before(Method method, Object[] args, Object target)
        throws Throwable {
     
    System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:before ----------------");
 
     String username=(String)args[0];
     String passowrd=(String)args[1];
      
    //在这里进行数据库查找操作
}

}
3. IUser.java

1
2
3
4
5
6
7
8
9
10
package com.laoyangx.Aop.chapter0;

public interface IUser {
/**
* 用户登录
* @param username 用户名
* @param password 密码
*/
public void Login(String username,String password);
}
4.UserImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.laoyangx.Aop.chapter0;

public class UserImpl implements IUser {

/**
 * 用户登录
 * @param username 用户名
 * @param password 密码
 */
@Override
public void Login(String username, String password) {
    System.out.println("---------- 程序正在执行  类名: com.laoyangx.Aop.chapter0.UserImpl 方法名:Login ----------------");
}

}
5. Spring 的配置文件 login.bean.xml

复制代码
复制代码

<?xml version="1.0" encoding="UTF-8"?>


com.laoyangx.Aop.chapter0.IUser loginAdvice 复制代码 复制代码 6.主程序文件 ConsoleApp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.laoyangx.Aop.chapter0;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ConsoleApp {

public static void main(String[] args) {
     
    ApplicationContext ctx=
        new ClassPathXmlApplicationContext("com/laoyangx/Aop/chapter0/login.bean.xml");
     
    IUser user=(IUser)ctx.getBean("user");
    user.Login("username", "123456");

}

}
运行程序之后,控制台上输出的结果

通过结果可以看到每个函数的执行顺序。关于 前置通知、环绕通知、后置通知 这些术语 网上都有相关的介绍

Spring组成的整体架构:

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图 1 所示。
图 1. Spring 框架的 7 个模块
Spring 框架图示

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP: 通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写 的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用

Stata实战:DID平行趋势检验完整操作指南(附reghdfe+coefplot代码) 本文提供了一份使用Stata进行DID平行趋势检验的完整实战指南。文章详细讲解了从数据准备、生成相对时间变量,到利用reghdfe命令构建动态效应模型,以及使用coefplot命令进行结果可视化的全流程操作。核心在于通过检验政策前交互项的显著性,验证处理组与对照组是否满足平行趋势假设,为后续因果推断奠定可靠基础。 阅读详情

相关推荐

VMware桥接模式实战:用手机热点给Linux虚拟机共享网络(附WiFi适配技巧)

本文详细介绍了在移动办公场景下,如何为VMware中的Linux虚拟机配置桥接模式,以通过手机热点共享网络。文章深入解析了桥接模式在无线环境下的工作原理,提供了从主机端准备、VMware设置到Linux虚拟机内部配置的完整实战步骤,并针对手机热点的特殊性,分享了MTU优化、DNS配置及常见网络问题的诊断与解决方案,帮助用户实现稳定高效的移动虚拟化办公。

2y3u4i5o6p的博客 1194

Spring学习笔记IOC与AOP实例,Spring框架2个核心

Spring学习笔记IOC与AOP实例 Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象。在以XML语言描述的配置文件中,声明web系统中哪个组件需要哪一种服务时,不是在程序中让对象和服务直接连接,具体负责连接工作的是Web容器,Spring中就是Ioc容器。 1 IoC的优...

ShiXinXin_Harbour的博客 700

百度贴吧爬虫实战:完整实现与使用指南

使用 csv 模块创建写入器,首先写入表头("标题" 和 "链接"),然后遍历帖子字典,将每个标题和链接作为一行写入文件。首先检查内容是否为空,然后通过查找 JSON 结构的起始({)和结束(})位置,提取有效的 JSON 片段。接着遍历帖子列表中的每个条目,提取标题文本和对应的链接,对于相对路径的链接会自动补全为完整的 URL。从 JSON 提取标题和链接此方法专门用于从解析后的 JSON 数据中提取帖子标题和对应的链接。提取到的标题和链接以字典形式返回,键为标题,值为对应的完整链接。

qq_63736560的博客 2016

Spring框架IOC和AOP的实现原理与详解

IoC(Inversion of Control)     (1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。 对于Spring而言,就是由Spring来控制对象的生命周期和对象之间的关系;IoC还有另外一个名字——“依赖注入(Dependency Inj

baidu_20876831的博客 3万+

电子技术设计——16×16点阵汉字显示设计

同时,设计还应注重提升显示品质,以保证汉字的稳定展示和观感舒适。本设计的目的是构建一个能够准确在LED点阵上展示汉字的系统,并允许用户通过输入设备来选择所需的汉字,我们将验证设计方案的实际操作性和效果,以确保其满足设计目标。在LED点阵显示和汉字信息处理技术的结合下,研究者们着手研究如何在LED点阵上有效地显示汉字,并提出了一系列显示算法和优化策略,旨在实现清晰且易于阅读的汉字显示效果。首先,你需要准备16×16的LED点阵面板,通常这些点阵是8×8点阵的两倍,因此可以由两个8×8的点阵组合而成。

weixin_68094467的博客 1533

经典算法之——解决全排列问题以及详解

回溯”指的是“状态重置”,可以理解为“恢复现场”,是在编码的过程中,是为了节约空间而使用的,而在递归或者深度优先中根据需要的场合来配合回溯法可以进一步对自己的代码进行优化。, n-1, n},方向都为向左。邻位对换法是全排列生成算法中的其中一种,它的换位是双向的,通过保存数字的“方向性”来快速得到下一个排列。最后以 3 开头的全排列为[3, 1, 2], [3, 2, 1];以 1 开头的全排列为[1, 2, 3], [1, 3, 2];以 2 开头的全排列为[2, 1, 3], [2, 3, 1];

m0_68987535的博客 8794

spring框架两大核心:IOC和AOP的详解

IOC和AOP的详解。

qq_49755675的博客 1万+

【实用运维脚本】Windows 批量 TCP 端口检测(tcping 一键巡检)

摘要:本文介绍一款高效的Windows批量TCP端口检测脚本,适配tcpingv0.39工具,实现多服务器一键巡检。脚本具有进度可视化、双日志输出、自动容错等优势,支持注释行过滤和UTF-8编码。 使用仅需三步: 1)下载tcping工具 2)编辑目标列表 3)运行脚本即可自动检测并生成带编号的检测报告。 该方案解决了手动检测效率低、易遗漏的问题,特别适合日常运维中的端口连通性检查,实测稳定可靠,开箱即用。

蕲士|D365 & 服务器运维,心有东坡,行稳致远。 798

Spring框架双核解析:IOC与AOP的本质与实战

将对象的“控制权”从程序员手中交给Spring容器,就像从“自己做饭”变成“点外卖”——只需声明需求,容器负责配送。:你在项目中是如何组合使用IOC和AOP的?控制多个切面的执行顺序。

weixin_52318532的博客 2343

Android 埋点信息分析——statsd框架

StatsPullAtomService 用以采集数据,并将数据填充到参数中,在StatsManager.PullAtomCallbackInternal 中会转换成 Parcel 格式传入到 native。 StatsCallbackPuller::PullInternal 中会回调StatsManager.PullAtomCallbackInternal 的onPullAtom,该函数中会回调StatsCallbackPuller::PullInternal 中定义的PullResultRecei

私房菜 2628

SAP自动化-ME51N批量创建采购申请

2、需要管理员授权RZ11脚本录制回放功能。1、仅限于正对SAP日常工作的批量处理。3、数据模板按实际需求更新。物料编码,工厂,数量。

小九啥也不会 529

Spring 框架的核心基础:IoC 和 AOP

IoC(Inversion of Control,控制反转),就是把对象创建和依赖关系的管理交给 Spring 容器,而不是由程序员手动去创建对象和管理依赖。IoC 以前是我们想要什么就自己创建什么,现在是我们需要什么容器就帮我们送来什么。IoC 是一种思想,DI 是实现 IoC 的具体方式,将一个对象所依赖的其他对象以参数的形式传入,由外部容器(如 Spring)来“注入”依赖,而不是对象自己创建。打个比方,你现在想吃炒菜和饭,点个外卖这时候就有人把炒好的菜和煮好的饭送到你手上。

m0_73748193的博客 1646

coredump文件的原理是啥

Core Dump(核心转储)是操作系统在程序崩溃(如段错误、非法指令等)时自动生成的一个文件,它包含了程序崩溃瞬间的。通过 core dump,开发者可以像“时间回溯”一样检查程序崩溃瞬间的状态,是调试复杂问题的利器!终止时,Linux 内核会生成 core 文件。不会生成 core dump,因为它们是“优雅终止”信号。这样 core 文件会直接压缩存储,节省磁盘空间。的文件(类似可执行文件),可以用。Core 文件本质上是一个。

二进制君 380

Spring框架的两大核心(Spring IOC、Spring AOP)

2、如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类。是将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

m0_73785340的博客 1237

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring 核心概念深度解析:IOC、DI 与 AOP

摘要: Spring框架通过IOC、DI和AOP三大核心机制革新了Java开发模式。IOC将对象控制权交给容器,降低耦合度;DI作为IOC的具体实现,提供构造器、Setter和字段三种注入方式。AOP则通过切面编程解决横切关注点问题,支持五种通知类型和两种代理方式。三者协同工作,使Spring成为高效、灵活的企业级开发框架,广泛应用于日志、事务、安全等场景,显著提升代码模块化和可维护性。(149字)

Java是世界上最好的语言 1904

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Spring 的 IOC 和 AOP 是什么,有哪些优点?解密 Spring两大核心概念:IOC与AOP的魅力所在

控制反转(Inversion of Control,IoC)是一种设计原则,它通过将对象的创建和管理交给Spring容器来实现解耦。这意味着在你的代码中,不再需要显式地创建对象,而是通过Spring提供的机制进行管理。面向切面编程(Aspect-Oriented Programming,AOP)是一种用于分离关注点的编程范式。AOP允许开发者在程序运行时动态地对代码进行横切关注(如日志、事务管理、安全控制)的描述和处理,而不需要修改业务逻辑代码。

智通全网络工作室的博客 2054

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring核心机制:IOC与AOP深度解析

Spring核心机制:IOC与AOP深度解析

嗨,欢迎来到我的 优快云 博客小天地!一名深耕多年的技术发烧友。在这里,我将把日常工作中积累的宝贵经验,从复杂架构设计的精妙之处,到代码优化的实战技巧,毫无保留地分享给大家。 1788

Java 手写 Spring框架 IOC 和 AOP----手写Spring IoC和AOP

本文将首先通过手写Spring,了解Spring基本思想,然后介绍Spring的一些高级用法,随后深度剖析其源码,让读者有更深入的了解====本文源码基于5.1.12版本讲解

殷志鹏的博客 2541

地基Spring框架中的​​IOC 、AOP ​​ 和 ​​DI

spring框架核心:IOC、AOP、DI

qq_37679639的博客 1170

【Spring框架三大核心特性】——IoC、DI、AOP

本文讲解 Spring 框架三大核心特性:控制反转(IoC),将对象创建等控制权交予 Spring 容器,实现解耦与灵活配置;依赖注入(DI),作为 IoC 的实现,通过构造器、Setter 方法等自动注入依赖,简化代码且便于动态替换;面向切面编程(AOP),分离日志、事务等横切关注点为切面,利用动态代理织入目标方法,实现代码复用与业务逻辑纯净,三者共同支撑 Spring 高内聚、低耦合的设计。

Mr.Ja的博客 1428

Spring框架的核心特性是什么?(IoC、AOP)

Spring框架通过IoC和AOP两大核心特性,实现了企业级应用的高效开发与维护。IoC容器通过依赖注入解耦组件,而AOP通过动态代理统一处理横切关注点,二者结合显著提升了代码的可复用性和可扩展性。随着Spring Boot和Cloud等子项目的成熟,Spring已成为构建现代Java应用的基石。

破损的天堂鸟博客 904

Spring IOC 与 Spring AOP

摘要:Spring框架通过IoC(控制反转)和AOP(面向切面编程)实现解耦与模块化。IoC容器负责对象创建与依赖注入,降低耦合度;AOP则将横切关注点(如日志、事务)从业务逻辑中分离,通过动态代理(JDK/CGLIB)实现织入。Spring AOP提供@Aspect等注解定义切面,支持多种通知类型。相比静态代理,动态代理更灵活高效。与功能更强大的AspectJ相比,Spring AOP轻量易用,适合大多数企业场景。IoC设计需考虑生命周期管理、依赖注入方式、作用域支持等核心机制。

PEI04的博客 1499

Spring框架;Spring中IOC简介及搭建;Spring中AOP简介;

Spring简介;Spring优点;Spring中IOC简介;SpringIOC环境搭建;Spring中Spring简介

weixin_72637723的博客 1419

Spring核心技术之Ioc和AOP

 一、Spring应用环境的配置: 1. 在classpath中添加以下包:    1) SPRING_HOME/dist/spring.jar、    2) SPRING_HOME/lib/jakarta-commons/commons-logging.jar    3) SPRING_HOME/lib/log4j/log4j-1.2.xx.jar 2.在classpath中添加Spring的配

Java之道 1万+

【Spring】两大核心基石 IoC和 AOP

本文深入解析了Spring框架的两大核心机制:IoC(控制反转)和AOP(面向切面编程)。IoC通过依赖注入将对象创建和管理权交给容器,推荐使用构造器注入方式。AOP则将横切关注点(如日志、事务)模块化为切面,通过动态代理实现非侵入式增强。文章详细介绍了二者的实现原理、关键术语和代码示例,并阐述了它们如何协同工作:IoC容器管理基础对象,AOP在此基础上进行功能增强,共同构建松耦合、易维护的企业级应用架构。

瘦到被风吹走的博客 1408

Spring IOC 与 AOP 核心原理深度解析

Spring IOC 与 AOP 核心原理深度解析

u011265143的专栏 1308
JavaSpringS
博客等级 码龄7年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值