怎么制作网站小游戏,企业手机网站建设策划,代理平台不再运营游戏,做实体上什么网站找项目Spring FrameWork一、 前言二、IOC(控制反转)2.1 对于IOC的理解2.2如何使用IOC2.3配置文件的解读2.4IOC容器创建bean的两种方式2.5从IOC容器中取bean2.6bean的属性如果包含特殊字符 三、DI(依赖注入)四、Spring中的bean五、Spring中的继承六、Spring的依赖七、Spring读取外部资… Spring FrameWork一、 前言二、IOC(控制反转)2.1 对于IOC的理解2.2如何使用IOC2.3配置文件的解读2.4IOC容器创建bean的两种方式2.5从IOC容器中取bean2.6bean的属性如果包含特殊字符 三、DI(依赖注入)四、Spring中的bean五、Spring中的继承六、Spring的依赖七、Spring读取外部资源八、Spring的p命名空间九、Spring工厂方法9.1静态工厂方法9.2实例工厂方法 十、Spring IOC 自动装配 autowire10.1自动装配10.2 Spring IOC基于注解的开发10.3实际开发中的使用 十一、Spring AOP 个人主页: 不断前进的皮卡丘 博客描述: 梦想也许遥不可及但重要的是追梦的过程用博客记录自己的成长记录自己一步一步向上攀登的印记 网站推荐千里之行始于足下。每天坚持刷题巩固所学知识也为将来找工作面试做好准备----- 刷题神器 文章是看楠哥的视频写的笔记 这篇博客内容把Spring的基本知识点都讲到了篇幅比较长大家可以用于复习也可以在学习相关知识点的时候来看看对应内容。对于一些难点IOC,AOP等我通过流程图代码文字结合来进行讲解可以更好的理解 Spring FrameWork
一、 前言
Spring是当前Java开发的行业标准第一框架Spring FrameWork已经从最初取代EJB的框架逐步发展成一套完整的生态最新的版本是5.xSpring架构体系图 Spring两大核心机制: IOC:工厂模式AOP:代理模式
二、IOC(控制反转)
2.1 对于IOC的理解 传统开发中需要调用对象的时候需要调用者手动来创建被调用者的实例即对象是由调用者new出来的 但是在Spring框架中创建对象的工作不再由调用者来完成而是交给IOC容器来创建再推送给调用者整个流程完成反转所以是控制反转 就比如说假设买东西以前我们需要自己去超市买东西但是现在我们可以不用自己去超市我们只要把购物袋放在家门口IOC就会自己去把我们想要的东西买回来然后放在袋子里面我们打开袋子拿起来用就可以了 IOC的特点是解耦合。 比如说A需要用到B传统的开发我们要直接创建B的实例但是在Spring中IOC这个容器会创建B的实例然后把这个B注入到A 2.2如何使用IOC
创建maven工程在pom.xml中导入相关依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdspringioc/artifactIdversion1.0-SNAPSHOT/versionpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.18/version/dependency/dependencies/project创建实体类Student
public class Student {private long id;private String name;private int age;public long getId() {return id;}public void setId(long id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return Student{ id id , name name \ , age age };}
}
在resources路径下创建applicationContext.xml配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idstu classcom.zyh.pojo.Student/bean
/beans传统的开发方式手动new Student Student stu new Student();stu .setAge(25);stu.setId(1001);stu.setName(张三);System.out.println(stu);IOC容器通过读取配置文件加载配置bean标签来创建对象就像买菜一样我们不需要自己亲自买但是要写一张单子告诉说要买什么程序也是类似的我们要告诉Spring框架要创建哪些对象怎样创建对象调用API从IOC获取对象
//读取配置文件ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);Student stu applicationContext.getBean(stu, Student.class);System.out.println(stu);2.3配置文件的解读
通过配置bean标签来完成对象的管理id:对象名class:对象的模板类(所有交给IOC容器来管理的类必须要有无参构造函数因为Spring底层是通过反射机制来创建对象调用的是无参构造)对象的成员变量通过property标签完成赋值 name:成员变量名value:成员变量值(基本数据类型String可以直接赋值如果是其他引用类型不可以通过value赋值)ref:把IOC中的另一个bean赋给当前成员变量(DI
2.4IOC容器创建bean的两种方式 无参构造函数(需要提供对应的set方法) 有参构造函数 bean idstu1 classcom.zyh.pojo.Studentconstructor-arg nameid value1 /constructor-argconstructor-arg namename value李四/constructor-arg/beanbean idstu1 classcom.zyh.pojo.Studentconstructor-arg index0 value1 /constructor-argconstructor-arg index1 value李四/constructor-arg/bean2.5从IOC容器中取bean
通过id取值 Student stu (Student)applicationContext.getBean(stu);通过类型取值 Student stu applicationContext.getBean( Student.class);当IOC容器中存在两个以上Student Bean的时候就会抛出异常因为此时没有唯一的bean
2.6bean的属性如果包含特殊字符 三、DI(依赖注入)
DI:指bean之间的依赖注入设置对象之间的级联关系Classes
public class Classes {private Integer id;private String name;还有对应的get,set方法
}Student
public class Student {private long id;private String name;private int age;private Classes classes;public Student(){System.out.println(使用无参构造创建对象);}public Student(long id,String name){this.id id;this.name name;} public Classes getClasses() {return classes;}public void setClasses(Classes classes) {this.classes classes;}public long getId() {return id;}public void setId(long id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return Student{ id id , name name \ , age age , classes classes };}
}
applicationContext-di.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idclasses classcom.zyh.pojo.Classesproperty namename value1班/propertyproperty nameid value1/property/beanbean idstudent classcom.zyh.pojo.Studentproperty nameid value1001/propertyproperty namename value张三/propertyproperty nameage value22/propertyproperty nameclasses refclasses/property/bean/beansbean之间的级联需要使用ref属性而不能用value属性否则会抛出类型转换异常
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idclasses classcom.zyh.pojo.Classesproperty namename value1班/propertyproperty nameid value1/propertyproperty namestudentListlistref beanstudent/refref beanstudent2/ref/list/property/beanbean idstudent classcom.zyh.pojo.Studentproperty nameid value100/propertyproperty namename value张三/propertyproperty nameage value22/propertyproperty nameclasses refclasses/property/beanbean idstudent2 classcom.zyh.pojo.Studentproperty nameid value200/propertyproperty nameage value18/propertyproperty namename value李四/propertyproperty nameclasses refclasses/property/bean/beans如果把学生装到班级里面又把班级装到学生里面就导致无限递归循环装配最终栈溢出
四、Spring中的bean
bean是根据scope来生成的表示bean的作用域scope有4种类型 singleton单例表示通过Spring容器获取的对象是唯一的是默认值 prototype原型表示通过Spring容器获取的对象是不同的 配置文件
bean iduser classcom.zyh.pojo.User scopeprototypeproperty nameid value1/propertyproperty namename value张三/property/beanrequest请求表示在异常HTTP请求内有效session会话表示在一个用户会话内有效 request和session一般用于web项目 singleton模式下只要加载IOC容器不管是否从IOC种取出bean,配置文件中的bean都会被创建而且只会创建一个对象 prototype模式下如果不从IOC中取出bean,则不创建对象取一次bean,就会创建一个对象
五、Spring中的继承
Spring中的继承不同于Java中的继承 Java中的继承是针对于类的 Spring中的继承是针对于对象(bean)
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean iduser1 classcom.zyh.pojo.User property nameid value1/propertyproperty namename value张三/property/beanbean iduser2 classcom.zyh.pojo.User parentuser1/bean
/beans通过设置bean标签的parent属性建立继承关系同时子bean可以覆盖父bean的属性值Spring的继承是针对对象的所以子bean和父bean并不需要同一个数据类型只要其成员变量列表一致即可
六、Spring的依赖
用来设置两个bean的创建顺序IOC容器默认情况下是通过applicationContext.xml中bean的配置顺序来决定创建顺序的配置在前面的bean会先被创建在不更改applicationContext.xml配置顺序的前提下通过设置bean之间的依赖关系来调整bean的创建顺序
七、Spring读取外部资源
在实际开发中数据库的配置会一般会单独保存到后缀为properties的文件方便维护和修改如果用Spring来加载数据源就需要在applicationContext.xml中读取properties中的数据这就是读取外部资源
jdbc.properties
userroot
passwordroot
urljdbc:mysql://localhost:3306/spring
driverNamecom.mysql.cj.jdbc.Driverspring-properties.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd!--导入外部资源 --context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.zyh.pojo.DataSourceproperty nameusername value${user}/propertyproperty namepassword value${password}/propertyproperty nameurl value${url}/propertyproperty namedriveName value${driverName}/property/bean/beans八、Spring的p命名空间
用来简化xml配置
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:phttp://www.springframework.org/schema/pxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idstu classcom.zyh.pojo.Student p:id1 p:age10 p:name张三 p:classes-refclasses/beanbean idclasses classcom.zyh.pojo.Classes p:name一班 p:id1/bean/beans九、Spring工厂方法
IOC通过工厂模式创建bean有两种方式
静态工厂方法实例工厂方法静态工厂类不需要实例化实例工厂类需要实例化
9.1静态工厂方法
创建Car类
public class Car {private Integer num;private String brand;public Car() {}public Car(Integer num, String brand) {this.num num;this.brand brand;}public Integer getNum() {return num;}public void setNum(Integer num) {this.num num;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand brand;}Overridepublic String toString() {return Car{ num num , brand brand \ };}
}
创建静态工厂类静态工厂方法
public class StaticCarFactory {private static MapInteger, Car carMap;static {carMap new HashMap();carMap.put(1, new Car(1, 奥迪));carMap.put(2, new Car(2,奥拓));}/*** 写一个方法从map集合取数据*/public static Car getCar(Integer num ){return carMap.get(num);}
}
spring-factory.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idcar classcom.zyh.factory.StaticCarFactory factory-methodgetCarconstructor-arg namenum value1/constructor-arg/bean/beansfactory-method 指向静态方法constructor-arg的value属性是调用静态方法传入的参数
9.2实例工厂方法
创建实例工厂类工厂方法
public class InstanceCarFactory {private MapInteger, Car carMap;public InstanceCarFactory() {carMap new HashMap();carMap.put(1, new Car(1, 奥迪));carMap.put(2, new Car(2, 奥拓));}public Car getCar(Integer num){return carMap.get(num);}}spring.xml
!-- 实例工厂类--bean idinstanceCarFactory classcom.zyh.factory.InstanceCarFactory/bean
!-- 通过实例工厂获取Car--bean idcar1 factory-beaninstanceCarFactory factory-methodgetCarconstructor-arg value2/constructor-arg/bean区别
静态工厂方法创建Car对象不需要实例化工厂对象因为静态工厂的静态方法不需要创建对象就可以调用了实例工厂方法创建Car对象需要实例化工厂对象因为getCar方法是非静态的就必须通过实例化对象才能调用所以 必须创建工厂对象spring.xml需要配置两个bean,一个是工厂bean,一个是Car Beanspring.xml中 classfactory-method的形式是直接调用类中的工厂方法spring.xml中factory-beanfactory-method的形式是调用工厂bean中的工厂方法就必须先创建工厂bean
十、Spring IOC 自动装配 autowire
10.1自动装配
自动装载是Spring提供的一种更加简便的方式来完成DI不需要手动配置propertyIOC 容器会自动选择bean来完成注入自动装载有两种方式 byName:通过属性名完成自动装载byType:通过属性对应的数据类型完成自动装载
byName的操作如下
创建Person实体类
public class Person {private Integer id;private String name;private Car car;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public Car getCar() {return car;}public void setCar(Car car) {this.car car;}Overridepublic String toString() {return Person{ id id , name name \ , car car };}
}在spring.xml中配置Car和Person对应的bean并且通过自动装载完成依赖注入
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idcar2 classcom.zyh.pojo.Carconstructor-arg namenum value1/constructor-argconstructor-arg namebrand value奥迪/constructor-arg/beanbean idcar classcom.zyh.pojo.Classes/beanbean idperson classcom.zyh.pojo.Person autowirebyName property namename value张三/propertyproperty nameid value2/property/bean/beans注如果bean的id有多个一致的会报错如Bean name car is already used in this beans element byType的操作如下
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idcar2 classcom.zyh.pojo.Carconstructor-arg namenum value1/constructor-argconstructor-arg namebrand value奥迪/constructor-arg/beanbean idcar classcom.zyh.pojo.Classes/beanbean idperson classcom.zyh.pojo.Person autowirebyType property namename value张三/propertyproperty nameid value2/property/bean/beans使用byType进行自动装配的时候必须保证IOC中有且只有一个符合如果有多个符合则报下面的异常
10.2 Spring IOC基于注解的开发
Spring IOC的作用是帮助开发者创建项目中所需要的bean,同时完成bean之间的依赖注入关系DI 实现该功能有两种方式
基于XML配置基于注解 基于注解有两步操作缺一不可
配置自动扫包添加注解
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd!-- 配置自动扫包--context:component-scan base-packagecom.zyh.pojo/context:component-scan
!-- bean idrepository classcom.zyh.pojo.Repository/bean--/beansComponent(valuerepository)
public class Repository {private DataSource dataSource;public DataSource getDataSource() {return dataSource;}public void setDataSource(DataSource dataSource) {this.dataSource dataSource;}Overridepublic String toString() {return Repository{ dataSource dataSource };}
}
DI 注解默认的beanid是类名以小写开头我们可以通过value来设置 如果我们想要把datasource也注入进来需要怎么做呢 首先我们要把DataSource先扫进来
Component
public class Repository {Autowiredprivate DataSource dataSource;public DataSource getDataSource() {return dataSource;}public void setDataSource(DataSource dataSource) {this.dataSource dataSource;}Overridepublic String toString() {return Repository{ dataSource dataSource };}
} Autowired默认是通过byType进行装配如果要改为byName,需要配合Qualifier注解来完成
Component
public class Repository {AutowiredQualifier(value datasource)private DataSource dataSource;public DataSource getDataSource() {return dataSource;}public void setDataSource(DataSource dataSource) {this.dataSource dataSource;}Overridepublic String toString() {return Repository{ dataSource dataSource };}
}
这表明把IOC中id为datasource的bean注入到repository中 实体类中普通的成员变量(String包装类等)可以通过Value注解来赋值
Component
public class DataSource {Value(root)private String username;Value(123456)private String password;Value(jdbc:mysql://localhost:3306/spring)private String url;Value(com.mysql.cj.jdbc.Driver)private String driveName;}10.3实际开发中的使用
实际开发中我们会把程序分成三层
ControllerServiceRepository(DAO)关系Controller—Service----Repository Component注解是把标注的类加载到IOC容器中实际开发中可以根据业务需求分别使用Controller,Service,Repository注解来标注控制层类业务层类持久层类
十一、Spring AOP
AOP (Aspect Oriented Programming) 面向切面编程OOP (Object Oriented Programming) 面向对象编程用对象化的思想来完成程序AOP是对OOP的一个补充是在另外一个维度上抽象出对象具体指程序运行时动态地把非业务代码切入到业务代码中从而实现程序的解耦合把非业务代码抽象成一个对象对对象编程就是面向切面编程上面这种形式的代码维护性很差代码复用性差 AOP的优点可以降低模块之间的耦合性提供代码的复用性提高代码的维护性集中管理非业务代码便于维护业务代码不受非业务代码影响逻辑更加清晰
通过一个例子来理解AOP。
创建一个计算器接口Cal
public interface Cal {public int add(int num1,int num2);public int sub(int num1,int num2);public int mul(int num1,int num2);public int div(int num1,int num2);
}
创建接口的实现类
public class CalImpl implements Cal {Overridepublic int add(int num1, int num2) {int res num1 num2;return res;}Overridepublic int sub(int num1, int num2) {int res num1 - num2;return res;}Overridepublic int mul(int num1, int num2) {int res num1 * num2;return res;}Overridepublic int div(int num1, int num2) {int resnum1/num2;return res;}
}日志打印
在每个方法开始位置输出参数信息在每个方法结束位置输出结果信息
对于计算器来说加减乘除就是业务代码日志打印就是非业务代码 AOP如何实现 使用动态代理的方式来实现 代理首先要具备CalImpl的所有功能(实现同一个接口)并且在这个基础上扩展出打印日志的功能
删除CalImpl方法中国所有打印日志的代码只保留业务代码创建MyInvocationHandler类(不是动态代理类)实现InvocationHandler接口生成动态代理类 。动态代理类需要动态生成需要获取到委托类的接口信息根据这些接口信息动态生成一个代理类然后再由ClassLoader用来把动态生成的类加载到JVM ClassLoader用来把动态生成的类加载到JVM中 代理类需要有和委托类一样的功能所以委托类和代理类需要实现同样的接口因此我们要获取到委托类的接口信息根据这个接口信息就可以生成一个类再通过ClassLoader加载到内存里面
public class MyInvocationHandler implements InvocationHandler {//委托对象private Object object null;//返回代理对象public Object bind(Object object) {this.object object;return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//实现业务代码和非业务代码的解耦合System.out.println(method.getName()方法的参数是: Arrays.toString(args));Object res method.invoke(this.object, args);System.out.println(method.getName()方法的结果是:res);return res;}
} 上述代码通过动态代理机制实现了业务代码和非业务代码的解耦合这是Spring AOP的底层实现机制真正使用 Spring AOP进行开发的时候不需要这么复杂 Spring AOP的开发步骤
创建切面类 Loggerspect
Component
Aspect
public class LoggerAspect {Before(execution(public int com.zyh.aop.impl.CalImpl.*(..)))public void before(JoinPoint joinPoint) {String name joinPoint.getSignature().getName();Object[] args joinPoint.getArgs();System.out.println(name 方法的参数是: Arrays.toString(args));}After(execution(* com.zyh.aop.impl.CalImpl.*(..)))public void after(JoinPoint joinPoint){String name joinPoint.getSignature().getName();System.out.println(name方法执行完毕);}AfterReturning(value execution(* com.zyh.aop.impl.CalImpl.*(..)),returning rs)public void afterReturning(JoinPoint joinPoint,Object rs){String name joinPoint.getSignature().getName();System.out.println(name方法执行的结果是:rs);}
AfterThrowing(value execution(* com.zyh.aop.impl.CalImpl.*(..)),throwing ex)public void afterThrowing(JoinPoint joinPoint,Exception ex){String name joinPoint.getSignature().getName();System.out.println(name方法抛出异常ex);
}}
Component,把切面类加载到IOC容器中Aspect,表示该类是一个切面类Before,表示方法的执行时机是在业务方法之前,execution表达式表示切入点是CalImpl中的所有方法After,表示方法的执行时机是在业务方法结束以后execution表达式表示切入点是CalImpl类中的方法AfterReturning,表示方法的执行时机是在业务方法返回结果后execution表达式表示切入点是CalImpl类中的方法returning是把业务方法的返回值和切面类方法的形参进行绑定AfterThrowing,表示方法的执行时机是在业务方法抛出异常后execution表达式表示切入点是CalImpl类中的方法throwing是把业务方法的异常和切面类方法的形参进行绑定
委托类也需要添加Component
Component
public class CalcImpl implements Calc{Overridepublic int add(int a, int b) {int resultab;return result;}Overridepublic int sub(int a, int b) {int resulta-b;return result;}Overridepublic int mul(int a, int b) {int result a*b;return result;}Overridepublic int div(int a, int b) {int result a/b;return result;}
}
3.spring-aop.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd!-- 自动扫包--context:component-scan base-packagecom.zyh.aop/context:component-scan
!-- 为委托对象自动生成代理对象--aop:aspectj-autoproxy/aop:aspectj-autoproxy
/beansaspectj-autoproxy Spring IOC容器会结合切面对象和委托对象自动生成动态代理对象AOP底层就是通过动态代理机制来实现的
4.测试 AOP的概念
切面对象根据切面抽象出来的对象CalImpl所有方法中需要加入日志的部分LoggerAspect通知切面对象具体执行的代码即非业务代码LoggerAspect对象打印日志的代码目标被横切的对象即CalImpl,把通知加入其中代理切面对象通知目标混合后的结果即我们通过JDK动态代理机制创建的对象连接点:需要被横切的位置即通知要插入业务代码的具体位置