Spring
IOC:控制反转,创建对象的工作由他完成
AOP:面向切面编程,不破坏源代码的情况下增加或者修改功能
IOC
IOC底层为:xml解析,工厂模式和反射
测试时候,先加载spring配置文件,在获取配置创建的对象,最后调用
IOC的重要接口:
-
BeanFactory:一般不用,使用时先解析xml文件,运行时才创建对象
-
ApplicationContext:是BeanFactory的加强版,使用时解析xml文件和创建对象
ApplicationContext有两个重要的实现接口:
-
FileSystemXmlApplicationContext:写入xml在盘中的地址
-
ClassPathXmlApplicationContext:写入xml类路径
-
spring有两种bean:
1.普通bean:创建什么类型,返回什么类型
2.FactoryBean:创建什么类型,可以返回不同的类型,具体实现方法是implement FactoryBean,然后重写其中的getObject方法,写要返回的类型,在调用时也要更改为自己想要的类型
IOC操作Bean的方式:
基于xml方式
-
创建对象
-
创建对象的时候默认使用无参构造,在xml文件中使用Bean标签
-
id属性:起别名,唯一标识
-
name属性:和id属性相似,可以有特殊符号
-
class属性:创建的对象所在的全路径(包类路径)
-
bean的作用域:标签scope。不写默认为singleton为单实例,在加载xml文件的时候就创建对象。prototype多实例,在调用context.getbean时才创建对象
-
-
注入属性
-
正常注入属性两种方式,写get然后new对象调get,有参构造器。
-
第一种方式get是在xml配置文件中,先写Bean创建对象,内部有property标签,分为name:属性名称和value:属性的值。相当于new对象和调get的工作在xml文件中完成了
-
如果注入的值为空值,在property标签中不写value,在property标签内写一个null标签
-
如果注入的值为特殊符号,例如<,必须使用转义字符或者写CDATE
-
如果注入的是对象,不写value,写ref
-
还有一种p空间注入,感觉不太清楚明了,底层是set注入
-
外部bean:前一个bean中赋值propery写name="zly",bean外面再写一个bean,id="zly"
-
内部bean,bean标签内还能写bean。是在propery标签内再写bean,再写propery赋值
-
级联赋值:涉及到对象要用ref,前一个bean中赋值propery写name="zly" ref="zly",bean外面再写一个bean,id="zly",内再写propery赋值,相当于外部bean的时候写个ref
-
注入集合类属性,在bean文件中,property标签中写其他标签,例如<List><Map><Set><array>,在里面在写<value>值
-
注入集合类属性时注入的为对象,则value不写,写为ref bean:,在外面创建对象,把id写道ref bean中
-
-
第二种方式有参构造器是在xml配置文件中,先写Bean创建对象,内部有constructor-arg标签,属性名称和value:属性的值。相当于new对象和有参构造的工作在xml文件中完成了
-
-
xml也可自动装配,在bean标签中有个autowire的标签,里面写ByName,或者ByType。省略了在中间使用property方式赋值
在学习了基于注解式的方法后,基于xml式的经典白学,不怎么使用
在xml文件中引入外部配置文件:一般用于链接数据库
使用德鲁伊连接池,先引入jar包,然后写一个jdbc.property文件,写入数据库信息,然后在xml文件中引入context名称空间,然后使用标签引入jdbc.property文件<context:property-placeholder location="classpath:jdbc.properties"/>,最后配置连接池用${}
基于注解式
基于注解式开发的步骤:
1.引入spring中aop依赖
2.在xml配置文件中告诉spring去哪个类扫描注解
<context:component-scan base-package="com.zly">/context:component-scan
写入要扫描的类,如果类很多可以用逗号隔开,或者写上层目录
<context:component-scan base-package="com.zly" use-default-filters="false"> <context:include-filter type="annotation" expression="com.zly.Controller"/> </context:component-scan> 这段添加了use-default-filters="false",不适用默认规则使用我们自己写的扫描规则,<context:include-filter只扫描后缀是Controller的类
<context:component-scan base-package="com.zly"> <context:exclude-filter type="annotation" expression="com.zly.Controller"/> </context:component-scan> 这段有<context:exclude-filter,表示不扫描包含Controller的类
3.写注解
@Component(value=“userservise”)
这个userservise相当于在Bean中的id
括号中的内容可以省略,省略之后默认为类名的开头小写,例如类名为Userservise,则id为userservise
-
创建对象
-
spring基于bean创建对象的注解
@Component
@Service
@Controller
@Repository
这四个注解可以混用,名称不同只是为了方便开发
-
-
注入属性
-
注入属性的时候不需要写set方法,注解帮忙实现了。要先定义类型再注入,例如private UserDao userDao,在这个上面写注解
-
spring基于bean注入属性的注解
@AutoWired 根据属性注入
@Qualifier 根据名称注入,一般和@Autowired一起使用,当一个接口中有多个方法时,根据属性注入没法分辨
@Resource可以根据属性注入,也可以根据名称注入。根据属性直接写,根据名称要写(name="名称"),不是spring中的,官方不建议使用
@Value注入普通类型属性
-
全注解式开发(在springboot中会着重讲解,主要使用,现在spring不使用)
-
实现全注解式开发,就是创建一个类,在类上写注解@Configuration,来代替xml配置文件,再写@ComponentScan(basePackages = {"com.zly"})里面写要扫描的路径。在测试中已经没有xml文件,所以要改为 ApplicationContext applicationContext=new AnnotationConfigApplicationContext(Config.class);
AOP
概念:面向切面编程,在一个功能中增加其他功能,不需要修改源代码,写一个新的模块通过配置文件插入就可以使用。降低了耦合度,提高了代码的复用。
底层原理:动态代理
-
有接口interface情况:使用JDK动态代理,创造接口实现类的代理对象来实现功能
-
无接口情况:一般实现是写方法的子类继承,然后重写进行扩展。aop使用CGLIB动态代理,创建子类的代理对象实现功能
基本概念
通知(增强):就是扩展了哪个方法,升级了哪个功能
-
前置通知,在方法调用前增强的功能@Before
-
后置通知@AfterReturning
-
异常通知@AfterThrowing
-
最终通知@After
-
环绕通知@Around
@Component @Aspect public class UserProxy { @Around("execution(* com.zly.User.add1(..))") public void add(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ System.out.println("环绕之前..."); proceedingJoinPoint.proceed(); System.out.println("环绕之后..."); } }
区别:后置通知是接受到返回值之后通知
最终通知是调用类后就通知
异常通知是出现异常后才通知,出现异常通知不执行后置通知
环绕通知要写不一样的代码
连接点:所有可以增强的方法
切入点:真正增强的方法,是连接点中的几个
切面:动词,表示把通知应用带切入点的过程
aop使用
1.spring中使用aop一般基于AspectJ,AspectJ不是spring中的组成部分,一般和spring框架联合使用
两种使用方式:
-
基于xml配置文件
-
基于注解式(常用)
2.导入jar包
3.切入点表达式:告诉要增强哪个切入点
execution(权限修饰符号 返回类型 类全路径 方法名称 参数列表)
权限修饰符一般用*,表示全类型 返回类型可以省略 参数列表用..表示方法中的参数
例1:对com.zly.UserDao中的add方法进行增强
execution(* com.zly.UserDao.add(..))
例2:对com.zly.UserDao中的所有方法进行增强
execution(* com.zly.UserDao.*(..))
例3:对com.zly包中的所有类里面的所有方法进行增强
execution(* com.zly.*.*(..))
抽取切入点:当使用多种通知,切入点表达式相同的时候,可以写一个方法加上@PointCut注解,之后调用时直接写方法名称
@Pointcut("execution(* com.zly.User.add1(..))") public void num(){ }
当多个增强类对一个方法增强,可以写注释@Order(数字)来区分优先级,数字越小,优先级越高
基于注解式开发
1.先在xml配置文件中写明要扫描的类是那些
2.创建子类和增强类的对象,注解式就行
3.在xml文件中开启AspectJ的使用
4.在增强类的类名上写@Aspect,在增强的方法上写是什么类型的@Before......,然后在括号中写切入点表达式
@Component @Aspect public class UserProxy { @Before("execution(* com.zly.User.add1(..))") public void add(){ System.out.println("before....."); } }
<context:component-scan base-package="com.zly"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
基于配置文件(未学,很少使用)
jdbcTemplete(未学,一般使用mybatis)
事务管理(未学看到springboot再回来)
日志管理
spring中封装了日志,但是不使用,一般使用log4j2。在spring5中不能使用log4j,要使用需要降版本为spring4
使用方法:
1.导入jar包
2.创建log4j.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="trace"> <!-- 配置日志信息输出目的地 --> <Appenders> <!-- 输出到控制台 --> <Console name="Console" target="SYSTEM_OUT"> <!--配置日志信息的格式 --> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <!-- 输出到文件,其中有一个append属性,默认为true,即不清空该文件原来的信息,采用添加的方式,若设为false,则会先清空原来的信息,再添加 --> <File name="MyFile" fileName="D:/Log4j2.log" append="false"> <PatternLayout> <!--配置日志信息的格式 --> <pattern>%d %p %C{1.} [%t] %m%n</pattern> </PatternLayout> </File> </Appenders> <!-- 定义logger,只有定义了logger并引入了appender,appender才会有效 --> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> <AppenderRef ref="MyFile"/> </Root> </Loggers> </Configuration>
spring新功能:(剩下的没看webflux和junit5测试框架)
@Nullable注解:
-
使用在方法上面,方法返回值可以为空
-
使用在方法的参数上面,参数返回值可以为空
-
使用在属性上面,属性的返回值可以为空