目录
1.什么是Spring
Spring是一个一站式的轻量级的开源框架:
1)一站式:因为Spring在每一层都提供了解决方法
2)轻量级:本身Spring就很小,10多kb,另外Spring和其他框架整合的时候也很小。
3)开源:Spring的源码托管到GitHub平台上,是优秀的开源的代码。
2.Spring的模块
Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)
1)IOC:Inverse Of Controll
1. 控制反转将new对象的过程去掉,将对象的生成交给Spring工厂去执行,也就是容器在对对象初始化的时候不等对象请求就直接将依赖传递给他。
2.IOC包括XML版本和注解版两种:
XML:
普通Bean的控制反转:
<beans>
<bean id="唯一标识:不能出现特殊字符;id可以不写 但是就得写name"
name="名称:理论上可以重复,实际上不重复;
name中可以出现特殊字符;
一般在Spring整合struts2时,name表示struts2的请求地址"
class="全限定类名"
scope="作用域:在整合struct2的时候需要指定scope
默认是sigloten单例;
prototype原型 多例;
request代表每一次请求生成一个实例; 不用
session 代表一次会话生成一个实例; 不用
application 代表每一个应用生成一个
websocket:WebSocket">
XXXXXXXXXXXX 用于java类的配置
</bean>
</beans>
静态工厂的控制反转:
<beans>
<bean id="userService"
class="com.sofwin.factory.ObjectFactory"
factory-method:"用于指定factory工厂中静态方法的方法名">
XXXXXXXXXXXXXXXXXXX - 用于java类的配置
</bean>
</beans>
实例工厂的控制反转
<beans>
<bean id="factory" class="com.sofwin.factory.ObjectFactory">
<bean id="userService" factory-bean="指定工厂bean的id" factory-method:"对应需要调用的普通方法的方法名">
XXXXXXXXXXXXXXXXXXXXX - 用于java类的配置
</bean>
</beans>
注解:第一步先开启组件扫描
第二步在自己写的类上面添加注解:
注解 | 描述 |
---|---|
@Component | 类级别的注解,用于生成JavaBean,可以用在控制层、业务层和DAO层 |
@Controller | 用作控制层 |
@Service | 用作业务层 |
@Repository | 用作DAO层 |
3.IOC控制反转主要是DI依赖注入和依赖查找
简单类型的属性DI依赖注入:
setter方法注入:
<bean id = "user" class="com.sofwin.pojo.User">
<property name="有公有setter方法的属性的属性名"
value="简单类型的属性值"
ref="另一个bean的id">
</property>
</bean>
构造方法注入:
<bean id = "user" class="com.sofwin.pojo.User">
<Constructor-arg name="构造方法中的形参名称"
value="形参代表的值"
index="标识当前参数在形参列表中的位置"
type="形参类型,用于有相同参数的构造方法的区别时使用"
ref="另一个bean 的 id">构造方法的属性>
</Constructor-arg>
</bean>
p命名空间:需要添加p命名空间的约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user"
class="com.sofwin.pojo.User"
p:属性="10"
p:ref="bean的id">
</bean>
spel表达式:和p命名空间一起使用
<bean id
class
p:id="#{T(java.lang.Math).random()*100}">
</bean>
集合类型的属性 DI依赖注入
property
<bean id="people"
class="com.sofwin.pojo.People">
<property name="pros">
<props>
<prop key="jdbc.url">jdbc:mysql:///demodb</prop>
<prop key="jdbc.username">root</prop>
</props>
</property>
</bean>
Map
<property name="map">
<map>
<entry key="name" value="name1"></entry>
<entry key="name" value-ref="需要注入的bean的id"></entry>
<entry key-ref="需要注入的bean的id" value="name"></entry>
<entry key-ref="需要注入的bean的id" value-ref="需要注入的bean的id"></entry>
</map>
XXXXXXXXXXXXX map属性注入
</property>
list
<property name="roles">
//集合泛型是自定义
<list>
<ref bean="需要注入的bean的id"></ref>
</list>
XXXXXXXXXXXXxxxxxx - list属性注入
</property>
<property name="ids">
//集合泛型是Integer
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
XXXXXXXXXXXXxxxxxx - list属性注入
</property>
set
<property name="ages"> 输出4个
<set>
<ref bean="role">
<value>1</value>
<value>2</value>
<value>2</value>
<value>3</value>
</set>
XXXXXXXXXXXXXXXXXXXXX - list属性注入
</property>
array
<property name="a">
//数组泛型是Integer
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
XXXXXXXXXXXXXXXXXXX - array属性注入
</property>
<property name="b">
//数组泛型是Role
<array>
<ref bean="role" ></ref>
</array>
XXXXXXXXXXXXXXXXXX - array属性注入
</property>
2)AOP
Aop是面向切面编程,是对面向对象的一个升级。
面向切面编程适用于解耦合,将耦合的代码提取出来,比如日志管理、事务处理等。
面向切面编程的原理:如果目标类实现接口,就是基于JDK的动态代理;如果目标类没有实现接口,就是基于cglib的动态代理。
我自己用过的AOP是基于AspectJ 的Aop,作过日志处理。
1.@Log自定义注解,用于操作日志编写 规定了type和msg ;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String module() default ""; //String
int operatorType(); //int
}
2.写一个增强类
-
类被@Aspect+@Compoment修饰;
-
写 普通方法,没有方法体且被@PointCut("@annotation()")修饰
-
写 普通方法,被@AfterThrowing(指定切入点表达式,抛出="ex")修饰 指定该方法是 异常增强
-
写 普通方法,被@AfterReturning(指定切入点表达式,结果="") 修饰 指定该方法是 后置增强
-
写 普通方法,handler(JoinPoint joinPoint,Object result,Integer status)
@Component
@Aspect
public class LogAspect {
@Autowired
private OperatorLogService operatorLogService;
@Autowired
private UserService userService;
//将自定义的注解 作为切入点表达式
@Pointcut("@annotation(com.sofwin.util.Log)")
public void a(){
}
@AfterReturning(pointcut = "a()",returning = "result")
public void afterReturning(JoinPoint joinpoint, Object result) throws JsonProcessingException {
handler(joinpoint,result,1);
}
@AfterThrowing(pointcut = "a()",throwing = "ex")
public void afterThrowing(JoinPoint joinpoint,Exception ex) throws JsonProcessingException {
handler(joinpoint,ex,0);
}
}
3.在每一项操作前增加@Log注解
@Controller
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 进入"弹出层" 进入编辑 或 新增页面
* @param id
* @param model
* @return
*/
@GetMapping("/toEdit")
@Log(module = "修改部门信息",operatorType = 2)
public String toEdit(Integer id, Model model){
if(id!=null){
//修改
SysDept dept = deptService.queryDept(id);
model.addAttribute("dept",dept);
String parent = deptService.queryParentNameByparentId(dept.getParentId());
model.addAttribute("parent",parent);
}
//新增
return "dept/edit";
}
/**
* 返回dept的页面信息
* @param dept
* @return pageInfo: total + list<SysDept>
*/
@GetMapping
@ResponseBody
@Log(module = "查询部门信息",operatorType = 1)
public ResponseEntity deptsInfo(SysDept dept){
List<SysDept> depts = deptService.queryDeptList(dept);
return ResponseEntity.success(depts);
}
/**
* 通过id查找到 dept对象 在删除、修改操作时用到
* @param id
* @return
*/
@GetMapping("/info/{id}")
@ResponseBody
@Log(module = "查询部门信息",operatorType = 1)
public ResponseEntity querydeptById(@PathVariable Integer id){
SysDept dept = deptService.queryDept(id);
if(dept.getId()!=null){
return ResponseEntity.success(dept);
}else
return ResponseEntity.error();
}
/**
* 根据id 删除部门信息
* @param id
* @return
*/
@DeleteMapping("/delete/{id}")
@ResponseBody
@Log(module = "删除部门信息",operatorType = 3)
public ResponseEntity deleteDeptById(@PathVariable Integer id){
boolean status = deptService.removeDept(id);
if(status){
return ResponseEntity.success();
}else
return ResponseEntity.error();
}
/**
* 批量删除
* @param ids
* @return
*/
@GetMapping ("/deletes")
@ResponseBody
@Log(module = "删除部门信息",operatorType = 3)
public ResponseEntity deleteDepts(@RequestParam(name = "ids")Integer[] ids){
Boolean status = deptService.removeDepts(ids);
if (status){
return ResponseEntity.success();
}else
return ResponseEntity.error();
}
/**
* 保存部门信息
* @param dept
* @return
*/
@PostMapping("/save")
@ResponseBody
@Log(module = "保存部门信息",operatorType = 0)
public ResponseEntity saveDept(SysDept dept){
boolean status = deptService.saveDept(dept);
if(status){
return ResponseEntity.success();
}else
return ResponseEntity.error();
}
}
总结:SpringAop是面向切面编程,他是对面向对象编程的一种升级,原理是动态代理,如果目标类实现了接口,就是基于jdk的动态代理,生成代理对象,如果目标类没有实现接口,就是cglib的字节码增强,也就是通过生成子类,来作为他的代理对象。
我用过AspectJAop,在日志中,自己定义一个日志的接口,再用作增强的类,@AspectJ修饰,定义切入点、前置、后置、环绕、异常、最终增强,最后在需要添加日志的方法上面引用注解@Log就可以