spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
注入对象:构造方法注入、stter方法注入、接口注入
简单实列:将对象放入Spring IOC容器中。
1.配置文件方式:
applictionContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="stu" class="SpringDemo.SpringDemo.Student">
</bean>
</beans>
main方法:
package SpringDemo.SpringDemo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
//加载前期解析xml,通过反射的方式创建出来,将对象放入Spring的IOC容器中
ApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");
//可以通过ApplicationContext的实例对象获取容器中已经存在的对象
Student student = (Student) context.getBean("stu");
System.err.println(student);
}
}
2.用@bean注解
package SpringDemo.SpringDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@Configuration // 声明此类是一个配置类
public class Config {
@Bean
public Grade createGrade() {
return new Grade();
}
}
ioc底层原理使用技术 (1)xml配置文件 (2)dom4j解决xml (3)工厂设计模式 (4)反射
AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取、并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。
AOP思想实现的关键在于AOP代理技术,AOP代理主要分为静态代理和动态代理。
静态代理的代表为AspectJ;动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
jdk代理 :JDK动态代理要求该业务Bean必须要有实现的接口,通过和该业务Bean–即目标对象,实现相同的接口保证功能一致。
cglib代理 : CGLib动态代理是通过继承该业务Bean–即目标对象,来保证功能一致,即,生成目标对象的子类, 这个子类对象就是代理对象。
1.JDKProxy动态代理类创建
package com.xia.jdk;
import com.xia.basic.User;
import com.xia.proxy.UserService;
import com.xia.proxy.UserServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TestJDKProxy {
public static void main(String[] args) {
// 1.创建原始对象
UserService userService = new UserServiceImpl();
// 2.创建动态代理
// InvocationHandler 实现额外功能
// 用于添加额外功能和之前的MethodInterceptor类似
// 其实就是对Invocation实现了封装
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// proxy 原始对象 method原始方法 args 方法参数
System.out.println("------JDKProxyBefore-----");
Object ret = method.invoke(userService,args);
System.out.println("------JDKProxyAfter-----");
return ret;
}
};
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
/*
* 类加载器功能
* 1.把对应类的字节码文件加载入jvm内存中
* 2.创建这个类的类对象 Class
* 3.借一个类加载器
* */
TestJDKProxy.class.getClassLoader(),
// 获得原始对象的所有的接口 这样就可以创建和原始类实现相同接口的代理类
userService.getClass().getInterfaces(),
// 额外功能
handler);
userServiceProxy.login(new User());
}
}
2.Cglib动态代理
public class TestCjLib {
public static void main(String[] args) {
// 创建原始对象
UserService userService = new UserService();
// cglib创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(TestCjLib.class.getClassLoader());
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib--before");
Object ret = method.invoke(userService, "夏冬","123456");
System.out.println("cglib--after");
return ret;
}
});
UserService userServiceProxy = (UserService)enhancer.create();
userServiceProxy.login("xiadong","123456");
}
}
总结:
jdk动态代理:通过接口创建代理类
cjlib动态代理:通过父类创建代理类
前面我们提到AOP主要应用一些非核心业务逻辑中,我们看看AOP常见的应用场景
监控
日志
缓存
鉴权
事务
异常处理
持久化
SpringMVC视图解析器解析流程:
1、将SpringMVC控制器中的返回结果封装成一个ModelAndView对象。
2、通过SpringMVC中的视图解析器,使用ViewResolver对控制器返回的ModelAndView对象进行解析,将逻辑视图转换成物理视图。
3、调用View中的render()方法对物理视图进行渲染。
1、@SpringBootApplication
替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
2、@ImportAutoConfiguration
导入配置类,一般做测试的时候使用,正常优先使用@EnableAutoConfiguration
3、@SpringBootConfiguration
替代@Configuration
4、@ImportResource
将资源导入容器
5、@PropertySource
导入properties文件
6、PropertySources
@PropertySource 的集合
7、@Role
bean角色定义为ROLE_APPLICATION(默认值)、ROLE_SUPPORT(辅助角色)、ROLE_INFRASTRUCTURE(后台角色,用户无感)
8、@Scope
指定bean的作用域,默认singleton,其它包括prototype、request、session、globalSession
9、@Lazy
使bean懒加载,取消bean预初始化。
10、@Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否者将抛出异常。
11、@Profile
指定Bean在哪个环境下被激活
12、@DependsOn
依赖的bean注册完成,才注册当前类,依赖bean不存在会报错。用于控制bean加载顺序
13、@PostConstruct
bean的属性都注入完毕后,执行注解标注的方式进行初始化工作
14、@Autowired
默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。
有两种事务控制的方法:编程式(硬编码,代码,API)vs 声明式(xml或注解)
声明式的好处:事务管理不侵入开发的组件,更改只需要在定义文件中出现配置即可。业务逻辑对象不会意识到处在事务管理之中,事实上也该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分。而且不需要事务管理时可关闭,符合开闭原则。(解耦)
Spring声明式事务控制底层就是aop。
例:@Transactional(rollbackFor = Exception.class)
首先,Spring 里面的核心功能是IOC容器,所谓IOC容器呢,本质上就是一个Bean的容器或者是一个Bean的工厂。
它能够根据xml里面声明的Bean配置进行bean的加载和初始化,然后BeanFactory来生产我们需要的各种各样的Bean。
所以我对BeanFactory的理解了有两个。
BeanFactory是所有Spring Bean容器的顶级接口,它为Spring的容器定义了一套规范,并提供像getBean这样的方法从容器中获取指定的Bean实例。
BeanFactory在产生Bean的同时,还提供了解决Bean之间的依赖注入的能力,也就是所谓的DI。
FactoryBean是一个工厂Bean,它是一个接口,主要的功能是动态生成某一个类型的Bean的实例,也就是说,我们可以自定义一个Bean并且加载到IOC容器里面。
它里面有一个重要的方法叫getObject(),这个方法里面就是用来实现动态构建Bean的过程。
Spring Cloud里面的OpenFeign组件,客户端的代理类,就是使用了FactoryBean来实现的。
SpringMVC的优点:
(1)使用简单,学习成本低。
(2)很容易就可以写出性能优秀的程序.
(3)灵活性强,Spring MVC的框架易扩展
SpringMVC的缺点:
(1)Spring与MVC 的Servlet API 耦合,难以脱离容器独立运行
(2)太过于细分,开发效率低
(3)过度追求完美,有过度设计的危险
解决的问题领域是:网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。
SpringBoot的优点:
1、创建独立Spring应用
2、内嵌web服务器
3、自动starter依赖,简化构建配置
4、自动配置Spring以及第三方功能
5、提供生产级别的监控、健康检查以及外部优化配置
6、无代码生成、无需编写XML
SpringBoot的缺点:
1、迭代快
2、封装太深,内部原理复杂,不容易精通
转:https://blog.csdn.net/y2020520/article/details/124951764
主要分为三层:基础支持层、核心处理层、接口层
基础支持层:数据源模块、事物管理器模块、缓存模块、Binding模块、反射模块、类型转换、日志模块、资源加载、解析器模块
核心处理层:配置解析、参数映射、SQL解析、SQL执行、结果映射、插件
接口层:SqlSession
MyBatis配置文件分为两类,一类是总配置文件,还有一类是写SQL语句的mapper文件。二者都是XML文件。
主配置文件:提供MyBatis的全局设置, 比方说 日志,数据源,mapper文件的位置等;主配置文件的所有配置信息都是在标签里面的
mapper文件: 主要就是写SQL语句的, 一般就是 一个表对应一个mapper文件。
1.@Param注解传参法(推荐)
2.Map传参法(推荐)
3.Java Bean传参法(推荐)
4.顺序传参法(不推荐)
一、占位符一:#{xxx}
PreparedStatement 预编译sql语句有?占位符。 xxx表达式的写法。
参数类型为javabean类, xxx表达式必须和javabean中属性对应的get方法名字一样。
如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称。
二、占位符二: ¥{xxx}
Statement拼接 sql语句没有? 占位符会有SQL注入的漏洞。xxx 表达式的写法。
参数类型为javabean类, xxx 表达式必须和javabean中属性对应的get方法名字一样,
如果parameterType传输单个简单类型值,{} 括号中只能是 value。
三、区别:
1.#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
2.$将传入的数据直接显示生成在sql中。如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
3.#方式能够很大程度防止sql注入。$方式无法防止Sql注入。
4.$方式一般用于传入数据库对象,例如传入表名.
5.一般能用#的就别用$.
一级缓存:SqlSession级别的缓存,缓存的数据只在SqlSession内有效。
二级缓存:mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的,二级缓存需要我们手动开启
mybatis类型转换器,就是Java类型与数据库的类型之间转换的一个中介,由这个转换器可以对类型进行映射,mybatis对于基础类型都有默认类型转换器,你可以自定义类型转换器替代默认的转换器,大多数情况下你无需替代它,但是对于Java中的复杂类型,比如对象想要映射成数据库的json字符串,那么你就可以自定义类型转换器。
mybatis自定义类型转换器可以继承TypeHandler或BaseTypeHandler两个接口,并实现其中的方法。
BaseTypeHandler继承TypeHandler,它们之间的关系使用了设计模式模板方法。
mybatis注解方式通过没有实现类的dao接口进行数据库操作的原理,一句话概括,就是jdk proxy,就是jdk代理
1)原理上:JDK动态动态代理的原理是根据 InvocationHandler 中的invoke()方法,由jdk为你的接口手动生成了一个实现了对应接口的类,因此,你的接口可以调用,这是理解mybatis接口没有实现类能被调用的关键。
2)功能上:可以看出mybatis中的接口就是XML文件的描述,一方面这样做的目的是和spring集成,将接口交给spring管理;另一方面是为了更加方便的管理XML文件(使用接口的package+interface作为namespace,method作为ID。
mybatis 与hibernate的对比:
Mybatis | Hibernate |
---|---|
开发效率 较容易上手;需要手动管理sql | 较难上手;无需管理sql,专注业务 |
入门 简单 | 入门 较难 |
sql更加灵活 | 几乎不用写sql,封装性较大 |
性能 相对较高 | 性能相对较低 |
优化 更容易 | 优化 较难 |
适用场合 1.有复杂的查询业务;2.无hibernate实践经验的 | 1.无复杂的查询业务;2.能够熟练应用hibernate的 |