MVC设计思想

历史问题:如果将大量的代码都写到一个方法中,后期维护不易

MVC说明:

1.M Model 数据层 数据处理/数据的持久化

2.V View 视图层 前端页面相关的内容(看到的内容)

3.C Control 控制层 控制数据的流转过程

层级代码结构

前提:在项目中代码需要松耦合,根据MVC指导思想,后端代码进行了优化,演变为现在的层级代码结构.

层级结构:

1.Controller层: 控制层,主要是用来实现与前端页面的交互!!!

2.Service层: 业务层,主要实现数据的处理!!!

3.Dao层/Mapper层: 持久层,与数据库进行交互.实现数据CURD操作!!!

4.POJO 根据数据表定义的实体对象

层级结构入门案例 :

1.定义表的实体对象层POJO层(User表,需要实现序列化接口)

package com.jt.demo10.pojo;
import java.io.Serializable;
public class User implements Serializable {//1.属性都是私有的,方法是公有的//2.实现序列化接口// 作用:(1)保证数据按照正确的格式输出!!!//      (2)在多线程条件下,共享数据必须序列化//3.POJO的对象一般都是用来实现数据的传递的private Integer id;private String name;private Integer age;private String sex;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 Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

2.定义Mapper级(面向接口编程—定义接口和实现类)
定义Mapper层接口:

package com.jt.demo11.mapper;import com.jt.demo11.pojo.User;public interface UserMapper {void addUser(User user);
}

定义Mapper层接口实现类:

package com.jt.demo11.mapper;import com.jt.demo11.pojo.User;
import org.springframework.stereotype.Repository;@Repository
public class UserMapperImpl implements UserMapper {@Overridepublic void addUser(User user) {System.out.println("操作成功:"+user.getName());}
}

3.定义Service层(面向接口编程—定义接口和实现类)

定义Service层接口:

package com.jt.demo11.service;import com.jt.demo11.pojo.User;public interface UserService {void addUser(User user);
}

定义Service层接口实现类:

package com.jt.demo11.service;import com.jt.demo11.mapper.UserMapper;
import com.jt.demo11.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic void addUser(User user) {userMapper.addUser(user);}
}

4.定义Controller层

定义Controller层类:

package com.jt.demo11.controller;import com.jt.demo11.pojo.User;
import com.jt.demo11.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserControl {@Autowiredprivate UserService userService;public void addUser(){User user = new User();user.setId(111);user.setAge(2021);user.setName("jdjjjj");user.setSex("KKKKK");userService.addUser(user);}
}

5.创建配置类

package com.jt.demo11.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("com.jt.demo11")
public class SpringConfig {}

6.创建测试类TestMVC

package com.jt.demo11;import com.jt.demo11.config.SpringConfig;
import com.jt.demo11.controller.UserControl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestMVC {public static void main(String[] args) {ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);UserControl c = app.getBean(UserControl.class);c.addUser();}
}

层级代码结构加载流程

1.用户执行main()方法,程序开始调用

2.spring容器开始执行ApplicationContext

3.spring容器按照指定的规则 加载配置类 注意包路径

4.根据配置类的注解,开始完成包扫描 @ComponentScan(“com.jt.demo10”)针对@Component注解有效

5.先扫描UserController,但是现在内存中没有依赖项UserService,所以当前线程先挂起(跳过!!!),继续执行后续动作

6.当程序解析到Mapper层时,可以直接实例化对象交给spring容器保存

7.当程序解析到Service层时,根据依赖注入的规则,注入Mapper的实现类,之后Service对象实例化成功

8.当程序加载完成之后,再次会到之前的Controller进行对象的注入,注入 UserService,之后UserController实例化成功,至些spring容器启动成功!!!

spring中AOP(面向切面编程)

面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容,是函数式编程中的一种衍生范程.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率.

AOP主要作用:在不修改原有代码的条件下,对方法进行扩展

IOC-DI和AOP之间的区别:

1.IOC-DI:利用第三方容器将对象统一管理.利用依赖注入为属性赋值,解决了对象与对象之间的耦合性的问题.(解决对象间的耦合问题)
升华:springMVC框架(对象)/Mybatis框架(对象)类似的框架都可以交给spring容器管理.spring可以以一种统一的方式管理其它第三方的框架,使得调用浑然一体,耦合低,解决了框架和框架之间耦合性问题.

2.AOP 名称为面向切面编程,使得业务逻辑各部分之间的耦合度降低(解决业务逻辑间的耦合问题)

动态代理

动态代理作用:

使用代理机制,可以有效降低代码的耦合性,将公共的代码/重复的代码,写到代理机制中,通过代理机制调用目标方法,使得真实的业务被调用,通过代理机制,可以有效的降低业务的耦合性.

代理的特点:
使用代理的对象和使用目标的对象看起来是一模一样的

动态代理分类(重点)
动态代理-JDK动态代理

1.JDK动态代理是JDK源码提供的,无需导入额外的jar包

2.JDK动态代理对象要求实现和被代理者相同的接口(代理对象和目标对象拥有相同数等且相同的方法,保证用户使用体验一样)—必须有接口

3.JDK动态代理创建速度快,运行时稍慢

  • 创建代理对象工具API

1.动态代理创建代理对象的API Proxy.newProxyInstance(loader,interfaces,h)

2.动态代理的参数几个/分别是谁 1.类加载器 2.接口数组 3.InvocationHandler处理器

3.代理对象调用方法时,为了扩展方法内容,调用处理器方法~~~

JDK动态代理示例:

1.定义业务类

业务接口

package com.jt.demo1.service;public interface UserService {void addUser();
}

业务类:

package com.jt.demo1.service;import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic void addUser() {System.out.println("新增用户成功!!!");}
}

2.JDK动态代理

//当前类是工具API,目的获取代理对象
public class JDKProxy {/*** public static Object newProxyInstance(ClassLoader loader,*                                           Class<?>[] interfaces,*                                           InvocationHandler h)* newProxyInstance方法参数说明:* ClassLoader loader,类加载器,将class加载到java运行机制中* Class<?>[] interfaces,被代理者的接口数组,java可以多实现接口* InvocationHandler h,将代理对象扩展的内容写到处理器中*/public static Object getProxy(Object target){//1.获取目标对象的类加载器ClassLoader loader = target.getClass().getClassLoader();//2.获取接口数组Class<?>[] interfaces = target.getClass().getInterfaces();//创建代理对象/*InvocationHandler headler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("事务开始");//调用  让目标方法执行  target:目标对象!!!其它的固定写法Object result = method.invoke(target, args);//让目标方法执行System.out.println("事务结束");return result;}};return Proxy.newProxyInstance(loader, interfaces,headler);*/return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("事务开始");//调用  让目标方法执行  target:目标对象!!!其它的固定写法Object result = method.invoke(target, args);//让目标方法执行System.out.println("事务结束");return result;}});}/*//获取InvocationHandler对象public InvocationHandler getInvocationHandler(Object target){//当代理执行业务操作时,通过InvocationHandler进行业务的扩展return new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("事务开始");//调用  让目标方法执行  target:目标对象!!!其它的固定写法Object result = method.invoke(target, args);//让目标方法执行System.out.println("事务结束");return result;}};}*/}

3.配置类

package com.jt.demo1.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("com.jt.demo1")
public class SpringConfig {}

4.测试类

public class TestTX {public static void main(String[] args) {//创建容器ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);//1.获取目标对象UserService target = app.getBean(UserService.class);//2.获取代理对象,JDK动态代理和目标对象必须实现同一接口,保持一模一样UserService proxy = (UserService) JDKProxy.getProxy(target);proxy.addUser();}
}
动态代理-CGLIB动态代理

1.CGLIB动态代理需要导入额外的jar包,才能使用

2.CGLIB被代理者有没有接口都可以,但是CGLIB代理对象是目标对象的子类(继承)

3.CGLIB动态代理创建速度慢,运行时快

关于动态代理总结:

为什么使用动态代理:实现了业务层的解耦

规则:将公共的代码/重复的代码,写到代理对象中,业务层只专注于自己的业务即可~~

AOP介绍

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

总结: Spring中的AOP 利用代理对象在不修改源代码的条件下,对方法进行扩展.

AOP专业术语

1).连接点: 用户可以被扩展的方法
2).切入点: 用户实际扩展的方法
3).通知: 扩展方法的具体实现
4).切面: 将通知应用到切入点的过程

AOP面向切面编程入门案例

1.引入aop的jar包,配置pom.xml文件,让maven导包

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.定义service层的接口和实现类

接口:

package com.jt.demo2.service;public interface UserService {void addUser();
}

接口的实现类:

package com.jt.demo2.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {@Overridepublic void addUser() {System.out.println("新增用户成功!!!");}
}

3.创建aop包,在包下创建切面类:

package com.jt.demo2.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/*** AOP  面向切面编程  1年开发* 知识铺垫:切面=动态代理+方法扩展  后期被AOP API封装*/
@Component
@Aspect  //标识当前类是一个切面
public class TxAspect {//编码:切面=切入点表达式+通知方法//切入点表达式:为谁创建代理对象!!!//bean后面的参为是实现类的key@Pointcut("bean(userServiceImpl)")public void pointCut(){}//通知方法:对原有方法的扩展@Before("pointCut()")public void before(){System.out.println("aop入门案例");}
}

4.创建配置类:

package com.jt.demo2.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.jt.demo2")
@EnableAspectJAutoProxy  //让AOP有效
public class SpringConfig {}

5.创建测试类,查看结果:

package com.jt.demo2;
import com.jt.demo2.config.SpringConfig;
import com.jt.demo2.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestAspect {public static void main(String[] args) {ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);//看上去:是目标对象  AOP:内部已经封装动态代理规则//实际上:已经被AOP封装,是一个代理对象UserService userService = app.getBean(UserService.class);System.out.println(userService.getClass());userService.addUser();}
}

注解:

1.@Aspect 标识当前类是一个切面

2.@Pointcut 标识切入点表达式

3.@Before 通知注解

4.@EnableAspectJAutoProxy 让AOP注解生效(在配置标识)

切入点表达式

作用:配置AOP为谁创建代理对象

  • bean标签

语法:bean(“spring管理对象的id”)

@Pointcut("bean(userServiceImpl)")   //userServiceImpl这个spring容器管理对象的key  首字母小字

功能:只能匹配固定的类/对象 一个,只能匹配一个,粗粒度匹配

  • within表达式

语法:within(包名.类名)

@Pointcut("within(com.jt.demo2.service.UserServiceImpl)")  //匹配单个容器管理对象
@Pointcut("within(com.jt.demo2.service.*)")  //匹配com.jt.demo2.service包下容器管理的所有类对象

功能:可以匹配多个类,粗粒度匹配

说明:bean/within都是粗粒度的匹配,匹配的是类(类中还有方法/方法还可以重载!!!)

  • execution表达式

    语法:execution(返回值类型 包名.方法名(参数列表))

    //void 类型匹配,创建动态代理对象,扩展方法正常运行
    @Pointcut("execution(void com.jt.demo2.service.UserServiceImpl.addUser())")
    //int 类型不匹配,创建动态代理对象失败,扩展方法无法运行
    @Pointcut("execution(int com.jt.demo2.service.UserServiceImpl.addUser())")
    //要求:拦截service.包下的所有的类,任间方法,任意参数  任意返回值类型
    @Pointcut("execution(* com.jt.demo2.service..*.*(..))")
    //service下的所有类用..*(两个点加星),任意参数用两个点(..)
    
  • @annotation自定义注解

1.自定义注解:

package com.jt.demo2.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD) //声明注解用在方法上
@Retention(RetentionPolicy.RUNTIME) //声明注解的生命周期
public @interface TX {}

2.使用自定义的注解标识需要动态代理的方法:

package com.jt.demo2.service;
import com.jt.demo2.anno.TX;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {@Override@TXpublic void addUser() {System.out.println("新增用户成功!!!");}
}

3.为addUser方法创建动态代理(先使用自定义注解标识方法,然后@annotation标识为方法创建动态代理)


@Component
@Aspect  //标识当前类是一个切面
public class TxAspect {@Pointcut("@annotation(com.jt.demo2.anno.TX)")public void pointCut(){}//通知方法:对原有方法的扩展@Before("pointCut()")public void before(){System.out.println("aop入门案例");}
}

通知方法:(通知方法一定得和切入点表达式绑定一起使用)

作用:当用户满足了切入点表达式,则才会执行 扩展的方法.

通知的类型
  • 前置通知 @Before 在目标方法执行前执行
 //通知方法:对原有方法的扩展@Before("pointCut()")   //前置通知,和切入点表达式的方法绑定public void before(){System.out.println("aop入门案例");}
  • 后置通知 @AfterReturning 在目标方法执行后执行
@AfterReturning("pointCut()")   //后置通知,和切入点表达式的方法绑定public void afterReturning(){System.out.println("AOP后置通知");}

后置通知可以记录目标方法的返回值结果,例如:

  /*记录目标方法的返回值结果returning:后置通知获取返回值的属性*/@AfterReturning(value="pointCut()",returning="result")   //在后置方法中获取方法的返回值,然后传到扩展方法使用public void afterReturning(Object result){System.out.println("AOP后置通知!!!");System.out.println("方法的返回值:"+result);}
  • 异常通知(目标方法执行时抛出异常时,异常通知执行)
@AfterThrowing("pointCut()")public void afterThrowing(){System.out.println("抛出异常执行!!!");}

获取异常信息

   /*说明:如果程序执行抛出异常,则可以由异常通知进行记录throwing:抛出异常的属性*/@AfterThrowing(value="pointCut()",throwing = "exception")public void afterThrowing(Exception exception){System.out.println("抛出异常执行!!!");//exception.printStackTrace();//打印详情异常信息,比较消耗内存日志信息System.out.println("异常信息:"+exception.getMessage());}
  • 最终通知:不管目标方法如何,最终都会运行
@After("pointCut()")public void after(){System.out.println("我是最终通知!!!");}
  • 环绕通知

    说明:

    1.前四大通知类型不能控制目标方法的运行,所以在使用时一般记录程序的运行状态

    2.在目标方法执行前后都要运行,只有环绕通知才可以控制目标方法是否运行,使用最多的通知方法

 /*注意事项:环绕通知中必须添加参数,并且必须位于第一位joinPoint.proceed()方法的作用:1.如果有下一个通知,则执行下一个通知;2.如果没有下一个通知,则执行目标方法!@return*/@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕通知开始");Object result = joinPoint.proceed(); //目标方法运行System.out.println("环绕通知结束");return result;}
关于连接点joinPoint的用法

说明:当用户调用方法时,如果该方法被切入点表达式匹配了,则spring会为其对象创建代理,则将这个方法称为连接点

连接点的作用:通过joinPoint对象可以获取当前方法的所有参数,可以供用户记录

通过连接点joinPoint获取目标对象的信息案例:

1.自定义注解

  @Target(ElementType.METHOD) //声明注解用在方法上@Retention(RetentionPolicy.RUNTIME) //声明注解的生命周期public @interface TX {}

2.定义接口和实现类以及使用注解用在需要创建动态代理的方法上

接口

package com.jt.demo2.service;public interface UserService {void addUser();}

接口实现类

  package com.jt.demo2.service;import com.jt.demo2.anno.TX;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl implements UserService {@Override@TXpublic void addUser() {System.out.println("新增用户成功!!!");}}

3.创建AOP切片类

@Component //切片类使用通用的Component注解
@Aspect  //标识当前类是一个切面
public class TxAspect {@Pointcut("@annotation(com.jt.demo2.anno.TX)")public void pointCut(){}//通知方法:对原有方法的扩展@Before("pointCut()")   //前置通知,和切入点表达式的方法绑定public void before(JoinPoint joinPoint){System.out.println("aop前置通知!!!");Class<?> targetClass = joinPoint.getTarget().getClass();//获取目标对象的类型System.out.println("目标对象的类型"+targetClass);String targetName = joinPoint.getSignature().getDeclaringTypeName();//获取目标对象的名称System.out.println("目标对象的名称:"+targetName);String methodName = joinPoint.getSignature().getName();//获取目标方法的名称System.out.println("目标方法名称:"+methodName);Object[] args = joinPoint.getArgs();//获取参数名称System.out.println("参数名称:"+ Arrays.toString(args));}
}

4.创建配置类

  package com.jt.demo2.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration@ComponentScan("com.jt.demo2")@EnableAspectJAutoProxy  //让AOP有效public class SpringConfig {}

5.测试类

package com.jt.demo2;
import com.jt.demo2.config.SpringConfig;
import com.jt.demo2.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestAspect {public static void main(String[] args) {ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);//看上去:是目标对象  AOP:内部已经封装动态代理规则//实际上:已经被AOP封装,是一个代理对象UserService userService = app.getBean(UserService.class);System.out.println(userService.getClass());userService.addUser();}
}

关于joinPoint和ProceedingJoinPoint区别

说明:

1.ProceedingJoinPoint只适用于环绕通知,国灰只有环绕通知,才能控制目标方法的运行

2.JoinPoint适用于其它的四大通知类型,可以用来记录运行的数据

3.ProceedingJoinPoint中有特殊的方法proceed();

4.如果使用"JoinPoint" 则必须位于参数的第一位

关于切面顺序研究

说明:spring中的AOP如果多个环绕通知参与,则采用嵌套的结构进行调用,执行的顺序与代码的顺序有关.

控制AOP的执行顺序用注解@Order(value=1):用value的值控制顺序

spring中默认代理策略

1.JDK动态代理 :被代理者必须有接口

2.CGLib代理:不管有没有接口都可以为其创建代理对象.代理对象是被代理者的子类(继承)

spring创建代理的规则:

如果目标对象有接口,则默认采用JDK动态代理模式

如果目标对象没有接口,则默认采用CGLib代理方式

代理模式的修改
说明如果需要改变默认的模式,则只能强制使用cglib代理模式(因为JDK动态代理的前提必须得有接口)

@EnableAspectJAutoProxy(proxyTargetClass = true)  //强制使用cglib动态代理
@EnableAspectJAutoProxy(proxyTargetClass = false)  //默认有接口使用JDK动态代理
@EnableAspectJAutoProxy  //默认有接口使用JDK动态代理

练习:

监控程序的运行时间 要求使用bean标签

记录目标对象类型class/目标对象的名称/目标方法的名称

1.定义接口和实现类

接口:

package com.jt.demo3.service;public interface UserService {void addUser();
}

接口的实现类:

package com.jt.demo3.service;import com.jt.demo3.anno.TX;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Override@TXpublic void addUser() {System.out.println("九九乘法表");for (int i = 1; i < 10; i++) {for (int j = 1; j <= i; j++) {System.out.print(i+"*"+j+"="+i*j);}System.out.println();}}
}

2.定义自定义注解

package com.jt.demo3.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TX {}

3.定义配置类

package com.jt.demo3.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.jt.demo3")
@EnableAspectJAutoProxy
public class Config {}

4.定义切片类

package com.jt.demo3.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component
@Aspect
public class TxAspect {@Around("@annotation(com.jt.demo3.anno.TX)")  //直接把切入点表达式写在通知方法后面,只能用一次public Object around(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();Object result = joinPoint.proceed();long end = System.currentTimeMillis();//获取参数System.out.println("获取类型:"+joinPoint.getTarget().getClass());System.out.println("获取目标对象的名称:"+joinPoint.getSignature().getDeclaringTypeName());System.out.println("获取方法名:"+joinPoint.getSignature().getName());System.out.println("耗时:"+(end-start));return result;}
}

5.测试类

package com.jt.demo3;import com.jt.demo3.service.UserService;
import com.jt.demo3.config.Config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestDemo {public static void main(String[] args) {ApplicationContext app = new AnnotationConfigApplicationContext(Config.class);UserService user = app.getBean(UserService.class);System.out.println(user.getClass());user.addUser();}
}

Spring总结

1.1 IOC-DI

(1) IOC:控制反转

对象的生命周期由spring容器管理

xml配置文件的写法:bean标签 id/class xml的容器的实现类ClassPathXmlApplicationcontext

注解写法 @bean 配置类

单例多例问题 默认是单例对象 @scope(“prototype”)多例对象

懒加载 @lazy 用户使用时才创建

spring生命周期方法 对象创建(无参构造)/对象初始化/业务调用/对象销毁

DI:依赖注入:根据spring中维护的对象,为自己的对象属性赋值(为对象的属性赋值)

简单属性赋值: @value注解

引用赋值: @Autowired

注入的方式: 1.Set注入 2.构造方法注入 3.工厂模式注入

1.2 AOP

什么是AOP 面向切面编程 在不修改源码的条件下,对方法进行扩展!!!解决了业务逻辑的耦合性

底层核心机制:动态代理机制(JDK动态代理和CGLIB动态代理 )

关键词:

切入点表达式:表示如果用户调用满足切入点表达式,则创建动态代理对象,执行aop的通知

通知方法(对业务的扩展):5个通知,环绕通知最为强大

连接点:用户调用的方法满足切入点表达式,则该方法称作为连接点

1.3 Spring框架的优势

(1)Spring框架的设计让程序从层级到业务实现了松耦合

(2)Spring基于这样的设计思想,可以整合其它的第三方框架,使得程序可以以一种统一的方式进行

02.springMVC设计思想及springAOP相关推荐

  1. 模仿SpringMVC的DispatcherServlet 手撸300行代码提炼精华设计思想并保证功能可用(1.0版本)

    前言 1.博客内容均出自于咕泡学院架构师第三期 2.架构师系列内容:架构师学习笔记(持续更新) 3.内容为手写SpringMVC的DistapcherServlet的核心功能,从V1版本到V2版本再到 ...

  2. 【设计思想解读开源框架】java监听模式和观察者模式

    深耕技术,啃下22个技术点 互联网行业更新换代非常快,行业常态便是不断学习,因此这些主流技术你一个都不能落下! ①并发编程 Java并发编程是整个Java开发体系中最难以理解,但也是最重要的知识点之一 ...

  3. 【完结】总结12大CNN主流模型架构设计思想

    文章首发于微信公众号<有三AI> [完结]总结12大CNN主流模型架构设计思想 专栏<CNN模型解读>正式完结了,在这一个专栏中,我们给大家回顾了深度学习中的各类具有代表性的C ...

  4. OLTP 系统和 OLAP 系统的核心设计思想

    关于 OLTP 系统和 OLAP 系统的核心设计思想 数据存储系统的关于查询的典型操作: -- 第一种需求: 根据 key(1) 找 value(name,age), 单点查询 select name ...

  5. Android应用程序和其设计思想--转载----做记录

    转载一篇Android 的先关文章,无论什么时候看都觉得有收获 文章来源地址 http://www.open-open.com/lib/view/open1466070376316.html 以下是正 ...

  6. 前端React教程第二课 React生命周期设计思想

    02 为什么 React 16 要更改组件的生命周期?(上) React 生命周期已经是一个老生常谈的话题了,几乎没有哪一门 React 入门教材会省略对组件生命周期的介绍.然而,入门教材在设计上往往 ...

  7. 《Spring设计思想》AOP设计基本原理

    0.前言 Spring 提供了AOP(Aspect Oriented Programming) 的支持, 那么,什么是AOP呢?本文将通过一个另外一个角度来诠释AOP的概念,帮助你更好地理解和使用Sp ...

  8. Android应用程序开发以及背后的设计思想深度剖析(4)

    特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处.作者系LiAnLab.org资深Android技术顾问吴赫老师.本系列文章交流与讨论:@宋宝华Barry 紧接连载三,我们接下从性 ...

  9. Spring核心和设计思想

    文章目录 1.Spring是什么? 什么是容器? 什么是IoC呢? 控制反转程序开发 理解Spring IoC DI概念 Spring的创建和使用 创建Spring项目 添加Spring框架支持 创建 ...

最新文章

  1. 1.5 不同类型的循环网络-深度学习第五课《序列模型》-Stanford吴恩达教授
  2. 堆 和 栈的 区别(经典)
  3. angular 点击事件阻止冒泡及默认行为
  4. 网页版nfc_苹果5大系统升级新特性浓缩汇总!秋季5G版iPhone稳了
  5. Tableau中的行级数据安全性——第2部分
  6. 科技界流传的 OKR 系统有用吗?
  7. Angular-Observable和RxJS
  8. 我们需要什么样的计算
  9. Asp.Net中的跨平台的
  10. 解决ichat模块调用过程中——登录微信网页版失败的方法
  11. 计算机视觉相关公开数据集(免费下载)
  12. R语言绘图—在绘图中实现截断值
  13. 顺丰快递查询api php,快递查询API接口_快递单号_申通顺丰数据接口 - 极速数据
  14. SYSLINUX 6.03不支持64bit的ext4
  15. 200个计算机局域网适合什么,批处理检测局域网电脑是否开机(200多台电脑,不同网段,最好按主机名称检测)...
  16. Fabric.js IText 手动设置斜体
  17. 当前疫情下火爆的直播应用,你了解背后的技术架构吗?
  18. 7、Spring事务配置下篇
  19. taylor+swift纽约公寓_欧美明星豪宅都有多美,眼见为实!
  20. Unity中制作动画

热门文章

  1. 北上广等一线城市IT岗位已接近饱和?
  2. 关于PS CC 不能直接拖图片的问题
  3. java CGLIB动态代理
  4. 百度地图受邀参加第九届全国化工物流行业年会 助力危化品物流运输安全合规
  5. 工厂模式C++实现(三种工厂模式附详细注释)
  6. C#读取txt 乱码问题的解决方案
  7. 网络安全_密码学实验_非对称加密算法RSA
  8. C++输入和输出:控制台I/O(键盘和屏幕)及文件I/O详细笔记
  9. Gluster部署案例
  10. SecureCRT远程连接虚拟机