1.spring层级代码结构
1.1 层级的划分
1.Controller层 @Controller
2.Service层 @Service
3.Dao/Mapper层 @Repository
4.POJO 根据数据表定义的实体对象
1.1.1 编辑pojo
package com.jt.demo10.pojo;
import java.io.Serializable;
public class User implements Serializable {
//1.属性都是私有的 方法是公有的 构造方法/get/set方法/toString
//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;
}
}
1.1.2 编辑mapper层
1.1.2.1 编辑mapper接口
package com.jt.demo10.mapper;
import com.jt.demo10.pojo.User;
public interface UserMapper {
//注意导包!!!
void addUser(User user);
}
1.1.2.2 编辑mapper实现类
package com.jt.demo10.mapper;
import com.jt.demo10.pojo.User;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//@Component
@Repository //Spring管理 key:userMapperImpl value:反射机制
public class UserMapperImpl implements UserMapper{
@Override
public void addUser(User user) {
System.out.println("完成用户的入库操作:"+user.getName());
}
}
1.1.3编辑service层
规则:被调用者一般都有接口和实现类
1.1.3.1 编辑UserService接口
package com.jt.demo10.service;
import com.jt.demo10.pojo.User;
public interface UserService{
void addUser(User user);
}
1.1.3.2 编辑UserService的实现类
package com.jt.demo10.service;
import com.jt.demo10.mapper.UserMapper;
import com.jt.demo10.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
@Service //将对象交给spring容器管理 key:userServiceImpl value:对象
public class UserServiceImpl implements UserService{
@AutoWired //根据类型匹配
private UserMapper userMapper;
@Override
public void addUser(User user){
userMapper.addUser(user);
}
}
1.1.4 编辑Controller层
package com.jt.demo10.controller;
import com.jt.demo10.pojo.User;
import com.jt.demo10.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void addUser(){
User user = new User();
user.setId(101);
user.setName("春节愉快");
user.setAge(2022);
user.setSex("男");
userService.addUser(user);
}
}
1.1.5 编辑配置类
package com.jt.demo10.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.jt.demo10")
public class SpringConfig {
}
1.1.6 编辑测试类
package com.jt.demo10;
import com.jt.demo10.config.SpringConfig;
import com.jt.demo10.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestMVC {
/**
* 1.熟练掌握IOC/DI原理
* 2.代码结构的嵌套 了解参数传递的规则.
* 3.将原有的面向对象 进行了高级的抽象 练习
* @param args
*/
public static void main(String[] args){
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = context.getBean(UserController.class);
userController.addUser();
}
}
1.1.7 层级代码调用流程图
1.1.8 层级代码结构加载流程
Map<UserMapperImpl,对象>
<UserServiceImpl,对象>
<UserController,对象>
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容器启动成功!!!
1.1.9 框架参数传递流程图
2. spring中的aop
2.1 aop介绍
面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术
利用aop可以对逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合性将降低,提高了程序的可重用性,提高了开发的效率
AOP的主要作用:在不修改源码的情况下,对方法进行拓展
2.2 IOC-DI / AOP之间的区别
1.IOC-DI利用第三方容器将对象统一管理,利用依赖注入位属性赋值,解决了对象与对象之间的耦合性问题
升华:SpringMVC框架(对象)/Mybatis框架(对象)类似的框架对象都可以交给spring容器管理,spring可以以一种统一的方式管理其他第三方的框架,使得调用浑然一体,
解决了框架与框架之间的耦合性问题
2.AOP 名称为 面向切面编程 使得 业务逻辑各部分之间的耦合性降低
2.3 传统代码开发问题
2.3.1 创建项目
2.3.2 清除多余文件
2.3.3 编辑测试案例
2.3.3.1 编辑UserService
1.定义接口
public interface UserService{
void addUser();
}
2.3.3.2 编辑UserServiceImpl
package com.jt.demo1.service;
import org.springframework.stereotype.Service;
public calss UserServiceImpl implements UserService{
/**
*业务要求:尽可能实现松耦合
* 分析:
* *1.Userservice是业务处理类 其中adduser方法完成用户新增
* 2.其中事务的代码和业务的代码紧紧耦合在一起
*3.如果事务的机制发生改变,则 所有的代码都将改变,耦合性高
*当前业务耦合性太高了!!!
*/
public void addUser(){
System.out.println("创建事务对象2");
System.out.println("事务开始2");
System.out.println("新增用户成功!!!");
System.out.println("事务提交2");
}
}
2.3.3.3 编辑测试类
package com.jt.demo1;
import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.service.UserService;
import com.jt.demo1.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestTx{
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean(UserService.class);
userService.addUser();
}
}
2.4 动态代理
2.4.1 动态代理作用
总结:使用代理机制,可以有效降低代码的耦合性,将公共的代码/重复的代码/写到代理机制中,通过代理机制调用目标方法,使得真实的业务被调用,通过代理锂机制可以有效降低业务的偶合性.
2.4.2 动态代理分类
代理特点:使用代理对象和使用目标对象看起来一模一样
2.4.2.1 动态代理–JDK动态代理
1.jdk动态代理是jdk源码提供的 无需导入额外的jar包
2.jdk代理对象要实现和被代理者相同的接口, 必须有接口
3.jdk代理创建速度快,运行时稍慢
2.4.2.2 动态代理 — CGLIB动态代理
1.cglib动态代理需要导入额外的jar包 才能使用
2.cglib要求被代理者有无接口都可以,但是cglib代理对象是目标对象的子类(继承)
3.cglib创建代理对象时稍慢,但是运行期速度快
2.5 动态代理实现----jdk代理
2.5.1 创建代理对象工具API—最主要的是处理器对象
1.动态代理创建代理对象的API Proxy.newProxyInstance(loader,interfaces,h);
2.动态代理的参数几个?分别是谁? 1.类加载器 2.接口数组 3.InvocationHandler 处理器
3.代理对象调用方法时,为了扩展方法内容,调用处理器方法
package com.jt.demo1.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//当前类是工具API 目的是获取代理对象
public class JDKProxy{
/**
参数说明:
1.classloader loader,类加载器 将class加载到java运行机制中
2.class<?>[] interfaces , 被代理者的接口数组 java可以多实现
3.invocationhandler h 将代理对象扩展的内容写在处理器中
*/
public static Object getProxy(Object target){
//1.获取目标对象的类加载器
ClassLoader loader = target.getClass().getClassLoader();
//2.获取接口数组
Class<?>[] interfaces = target.getClass().getInterfaces();
//3.获取处理器对象
InvocationHandler h = getInvocationHandler(target);
//4.创建代理对象
return Proxy.newProxyInstance(loader,interfaces,h);
}
//获取InvocationHandler对象
public static InvocationHandler getInvocationHandler(Object target){
//当代理对象执行业务操作时,通过InvocationHandler进行业务扩展
return new InvocationHandler(){
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
System.out.println("事务开始");
//调用 让目标方法执行 target:目标方法!!! 其他都是固定写法 就记这里就可以!!!!---------这里只需要记住怎么传参就行 就是invoke 的参数
Object result = method.invoke(target args);
System.out.println("事务提交");
return result;
}
};
}
}
2.5.2 动态代理实现方法扩展
package com.jt.demo1;
import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.proxy.JDKProxy;
import com.jt.demo1.service.UserService;
import com.jt.demo1.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestTx{
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
//1.获取目标对象 userServiceImpl 接口UserSesrvice 实现类对象
UserService target = context.getBean(UserService.class);
//2.获取代理对象 实现了UserService接口
UserService proxy = (UserService) JDKProxy.getProxy(target);
proxy.addUser();
}
}
2.6 动态代理总结
为了实现业务层的解耦
规则:将公共的代码/重复的代码 写到代理对象中,业务层只专注于自己的业务即可