1.Spring 层级代码结构
1.1 层级的划分
1. Controller 层 @Contorlller
2. Service 层 @Service
3. 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编辑UserMapper接口
package com.jt.demo10.mapper;
import com.jt.demo10.pojo.User;
public interface UserMapper {
//注意导包!!!
void addUser(User user);
}
1.1.2.2 编辑UserMapper实现类
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 编辑UserServiceImpl实现类
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 编辑控制层
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容器开始执行ApplicationcContext
3.spring容器按照指定的规制加载配置类
4.根据配置类的注解开始完成包扫描@ComponentScan("com.jt.demo10")针对@Component注解有效;
5.如果先扫描到UserController,但是类中没有依赖项给UserService属性赋值,这线程先挂起来,继续往后扫描;
6.当程序解析到UserMapper,可以直接实例化对象交给spring容器管理;
7.当程序解析到UserService,根据依赖注入,给mapperService 属性注入Mapper的实现类,之后UserService类实例化成功
8.当程序加载完成之后,再次回到之前Controller对象挂起的地方,注入UserSevice 的实例对象,然后UserController实例化成功,至此Spring容器启动成功;
1.1.9 框架参数传递流程图
2. Spring中Aop
2.1 Aop介绍
面向切面编程通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术;利用AOP可以对业务逻辑的各个部分进行隔离,从而使的业务逻辑各部分之间的耦合性降低;
AOP主要作用:在不修改原有代码的情况下对方法进行扩展
难点词语:
1.切面
2.预编译
3.动态代理
2.2 IOC-DI/AOP之间的区别
1.IOC-DI 利用第三方容器将对象统一管理,利用依赖注入为属性赋值,解决力对象和对象之间的耦合性问题;
升华:SpringMVC框架(对象),Mybatis框架(对象)类似的框架都可以交个Spring容器统一管理,解决了框架和框架之间的耦合性问题
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 编辑实现类
package com.jt.demo1.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
/**
* 业务:要求 尽可能松耦合
* 分析:
* 1.UserService是业务处理类,其中addUser方法完成用户新增.
* 2.其中事务的代码与业务代码紧紧的耦合在一起.
* 3.如果事务的机制发生了变化,则所有的代码都将改变.耦合性高
* 当前业务耦合性太高了!!!
*/
@Override
public void addUser() {
System.out.println("创建事务对象2");
System.out.println("事务开始2");
System.out.println("新增用户成功!!!");
System.out.println("事务提交2");
}
}
2.4 动态代理
2.4.1动态代理的作用
总结:使用代理机制可以有效的降低代码的耦合性,将公共的代码/重复的代码,写到代理机制中,通过代理机制调用目标方法使的真实的业务被调用,可以有效的降低业务的耦合性
2.4.2 动态代理分类
代理特点:使得代理对象和代理目标看起来一模一样;
2.4.2.1 动态代理-jdk动态代理
1.jdk动态代理是java 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 ProxyInstance(loader,interfaces,h);
package com.jt.demo1.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//当前类是工具API,目的获取代理对象
public class JDKProxy {
/**
* 参数说明:
* ClassLoader loader, 类加载器:将class加载到java运行机制中
* Class<?>[] interfaces, 被代理者的接口数组 java可以多实现
* InvocationHandler h 将代理对象扩展的内容写到处理器中
* @param target
* @return
*/
public static Object getProxy(Object target){
//1.获取目标对象的类加载器
ClassLoader loader = target.getClass().getClassLoader();
//2.获取接口数组
Class<?>[] interfaces = target.getClass().getInterfaces();
//3.获取处理器对象
InvocationHandler h = getInvocationHandler(target);
//创建代理对象
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:目标对象!!!! 其它都是固定写法!!!
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 关于动态代理的总结
为什么用动态代理:实现业务层的解耦;
规则:将公共的重复的代码写到代理对象中,业务层只专注于业务即可