Spring
核心技术 (spring)
导入Spring开发的基本包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
|
组成

基于Spring的开发:
Spring | Home

- Spring Cloud
- SpringCloud 是基于SpringBoot实现的
常用配置
依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> </dependency> </dependencies>
|
配置
<?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:context="http://www.springframework.org/schema/context" xmlns:contex="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<contex:component-scan base-package="com.chen.pojo"/>
<context:annotation-config/> <aop:aspectj-autoproxy/>
</beans>
|
注解说明
@component 【等价】 【@Repository】 【@Service】 【@Controller】
@Value("Value")
|
@Autowired @Autowired(required = fasle)
@Autowired @Qualifier(value="id_Name")
@Resource @Resource(name="指定id_Name")
|
@Aspect
@Before("execution(表达式)")
@After("execution(表达式)")
@Around("execution(表达式)")
|
IOC
1.推理导论(set注入)
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spig中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency In可jection,Dl)。
1.UserDao接口
2.UserDaolmpl 实现类
3.UserService 业务接口
4.UserServicelmpl 业务实现类
原来需要什么方法则new该对象出现使用其方法
private UserDao userDao=new UserDaoImpl(); private UserDao userDao=new UserDaoMysqlImpl(); private UserDao userDao=new UserDaoOracelImpl();
|
Set方式注入
现在使用set方法注入对象(可理解为封装)
使用一个Set接口实现.已经发生了革命性的变化!
private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; }
|
UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(new UserDaoImpl()); userService.setUserDao(new UserDaoMysqlImpl()); userService.getUser();
|
- 之前,程序是主动创建对象!控制权在程序猿手上!
- 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!– 控制反转
2.Spring托管对象
核心技术 (spring.io)
对象是谁创建的?
对象是由Spring创建的
对象的属性是怎么设置的?
对象的属性是由Spring容器设置的,
这个过程就叫控制反转
基于 XML 的配置元数据的基本结构(Bean):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mysqlImpl" class="com.chen.dao.UserDaoMysqlImpl"/> <bean id="oraclelImpl" class="com.chen.dao.UserDaoOraclelImpl"/>
<bean id="UserServiceImpl" class="com.chen.service.UserServiceImpl">
<property name="userDao" ref="mysqlImpl"/> </bean>
</beans>
|
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
UserServiceImpl userServiceImpl = context.getBean("UserServiceImpl",UserServiceImpl.class);
userServiceImpl.getUser();
|
对象由Spring来创建,管理,装配
3.IOC构造器注入
1.使用无参构造创建对象,默认!
2.假设我们要使用有参构造创建对象。
1.下标赋值
<bean id="user" class="com.chen.pojo.User"> <constructor-arg index="0" value="辰呀"/> </bean>
|
2.类型
<bean id="user" class="com.chen.pojo.User"> <constructor-arg type="java.lang.String" value="chen"/> </bean>
|
3.参数名* name 【*】
<bean id="user" class="com.chen.pojo.User"> <constructor-arg name="name" value="辰辰呀"/> </bean>
|
总结:在配置文件加载的时候,容器中管理的对象就已经初始化
Spring 配置
别名
<alias name="User" alias="userc"/>
|
Bean的配置
<bean id="userT" class="com.chen.pojo.UserT" name="user2 userc,userp"/>
|
import
<import resource="beans1.xml"/> <import resource="beans2.xml"/>
|
使用时直接使用总的配置即可。
依赖注入
1.构造器注入
<bean id="user" class="com.chen.pojo.User"> <constructor-arg name="name" value="辰辰呀"></constructor-arg> </bean>
|
2.Set方式注入【重点】
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入
【环境搭建】
private String name; private Adress adress; private String[] books; private List<String> hobbys; private Map<String,String>card; private Set<String> games; private Properties info; private String wife;
|
<bean id="address" class="com.chen.pojo.Adress"> <property name="tid" value="12"/> <property name="name" value="PC"/> </bean>
<bean id="student" class="com.chen.pojo.Student"> <property name="name" value="辰呀"/>
<property name="adress" ref="address"/>
<property name="books"> <array> <value>红楼梦</value> <value>西游记</value> </array> </property>
<property name="hobbys"> <list> <value>看电影</value> <value>敲代码</value> </list> </property>
<property name="card"> <map> <entry key="身份证" value="1111111111111111"></entry> <entry key="" value=""/> </map> </property>
<property name="games"> <set> <value>LOL</value> <value>COC</value> </set> </property>
<property name="wife"> <property name="wife" value="12"/> <null></null> </property>
<property name="info"> <props> <prop key="键">值</prop> <prop key="学号">20215120</prop> <prop key="性别">男</prop> </props> </property> </bean>
|
测试类:
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.toString()); }
|
3.拓展方式注入
约束
<?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" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
|
p命名空间注入
<bean id="student" class="com.chen.pojo.Student" p:name="辰呀" p:age="18"/>
|
c命名空间注入
<bean id="user2" class="com.chen.pojo.User" c:age="22" c:name="辰呀cc"/>
|
测试
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml"); User user = (User) context.getBean("user2"); System.out.println(user); }
|
注意点:p命名空间和c空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
|
Bean的作用域
1.单例模式(Spring 默认机制 多个对象共享一个bean)
<bean id="user2" class="com.chen.pojo.User" c:age="22" c:name="辰呀cc" scope="singleton"/>
|
2.原型模式(每个bean都对应一个单独对象)每次从容器get的时候,都会产生一个新对象
<bean id="user2" class="com.chen.pojo.User" c:age="22" c:name="辰呀cc" scope="prototype"/>
|
3.其余的request、session、application,这些只能在web开发中使用到
Bean自动装配
在Spring中的三种装配的方式
在xml显显式的装配
<bean id="user2" class="com.chen.pojo.User" c:age="22" c:name="辰呀cc" scope="prototype"/>
|
在java中显式配置
隐式的自动装配bean【重要**】
1.测试
环境搭建
2.autowire - Byname
<bean id="b" class="com.chen.pojo.B"/> <bean id="c" class="com.chen.pojo.C"/>
<bean id="a" class="com.chen.pojo.A" autowire="byName/byType">
|
byName总结:
- 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性set方法的值一致
3.autowire – ByType
<bean id="b" class="com.chen.pojo.B"/> <bean class="com.chen.pojo.C"/>
<bean id="a" class="com.chen.pojo.A" autowire="byName/byType">
|
byName总结:
byType总结:
4.使用注解实现自动装配
将Spring容器中已经注册的bean进行注解装配给目标对象
使用注解:
1.导入约束 – context 约束
xmlns:context="http://www.springframework.org/schema/context"
|
2.配置注解的支持: context:annotation-config/
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/>
</beans>
|
@Autowired
<context:annotation-config/> <bean id="cat" class="com.chen.pojo.Cat"/> <bean id="dog" class="com.chen.pojo.Dog"/> <bean id="person" class="com.chen.pojo.Person"/>
|
- 直接在属性上使用即可,也可以在set方式上使用
- 使用Autowired 我们可以不用编写Set方法,前提是这个自动装配的实现在IOC(Spring)容器中存在,id且符合名字byname(bytype先后byname都会相辅相成执行)
public class Person { @Autowired private Cat cat; @Autowired private Dog dog; private String name; }
|
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(Value=”xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入
<bean id="cat1" class="com.chen.pojo.Cat"/> <bean id="cat2" class="com.chen.pojo.Cat"/>
@Autowired @Qualifier(value="cat2") private Cat cat;
|
@Resource
先通过id名称(不唯一)查找、后会通过类型class(唯一)查找,自行选择(name=” “)
@Resource private Cat cat;
@Resource(name="cat2") private Cat cat;
|
总结:
@Autowired和@Resource的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 通过 byType 的方式实现,而且必须要求这个对象存在!【常用】
- @Resource 默认通过 byname 的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到则报错
- 执行顺序不同:
使用注解开发
- 使用注解需要导入 context 约束,增加注解的支持
<?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:context="http://www.springframework.org/schema/context" xmlns:contex="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<contex:component-scan base-package="com.chen.pojo"/>
<context:annotation-config/>
</beans>
|
- 使注解生效:component-scan – 指定要扫描的包 ,这个包下的注解就会生效
<contex:component-scan base-package="com.chen.pojo"/>
|
@Component
在类中使用 @Component 完成装配
则无需由bean创建对象 – id为类名小写
@component 等价于 < bean id=”user” class=”com.chen.pojo.User” />
@Component public class User { public String name="辰呀"; }
|
Test
.getBena(“默认为类名的小写”)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); System.out.println(user.name);
|
@Value
等价于 : < property name=”name” value=”辰呀” />
public class User { @Value("辰呀") public String name; @Value("辰呀") public void setName(String name){ this.name=name; } }
|
衍生注解
@Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
【该类被spring托管,实现自动装配】
dao【@Repository】
service【@Service】
controller 【@Controller】
这四个注解功能都是一样的 ,上三个等价 @Component,都是代表将某个类注册到Spring中,装配Bean
作用域 Scope
@Component @Scope("singleton") public class User { public String name="辰呀"; }
|
xml更加万能,适用于任何场合!维护简单方便
注解不是自己类使用不了,维护相对复杂
Xml用来管理bean:
注解只负责完成属性的注入:
我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<contex:component-scan base-package="com.chen.pojo"/>
<context:annotation-config/>
|
注解说明
- @Autowired: 自动装配通过类型。名字如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=”xx”)
- @Nullable 字段标记了这个注解,说明这个字段可以为null;
- @Resource: 自动装配通过名字。类型。
- @Component: 组件,放在类上,说明这个类被Spring管理了,就是bean!
- @Repository – dao层
- @Service – service层
- @Controller – controller层
使用JavaConfig实现配置
- 想法:我们现现在完全不使用Spring的xml配置了,全权交给Java来做,就是说把xml配置文件转为java程序
- JavaConfig 是Spring 的一个子项目,在spring 4 之后,成为了核心功能
.@bean可以用于通过方法获取数据库连接池Connect ion这种对象
注意:1.如果开启包扫描,加载配置类以后就可以通过反射拿到配置类中的对象了,
2.@Bean只写在方法上,返回的是一个对象,但一般不获取已经在容器中的对象
@Component public class User { private String name;
public String getName() { return name; }
@Value("C辰呀") public void setName(String name) { this.name = name; }
@Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
|
@Configuration
@ComponentScan("com.chen.pojo")
@Import(ChenConfig2.class)
public class ChenConfig { <bean id="getUser" class-"com.chen.pojo.User"/> @Bean public User getUser(){ return new User(); }
}
|
public class Mytest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ChenConfig.class); User user =context.getBean("getUser",User.class); System.out.println(user.getName()); } }
|
这种纯Java的配置方式,在SpringBoot中随处可见
代理模式
- AOP的实现机制利用代理实现业务拓展
- 代码:Spring-08-demo2-demo4

静态代理
角色分析:
- 抽象角色:一般使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操纵
- 客户:访问代理对象的人
代理步骤:
1.接口
public interface Rent { public void rent(); }
public interface UserService { public void add(); public void delete(); public void update(); public void query();
}
|
2.真实角色
public class Host implements Rent{ @Override public void rent() { System.out.println("房东要出租"); } }
public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个用户"); }
@Override public void delete() { System.out.println("删除了一个用户"); }
@Override public void update() { System.out.println("修改了一个用户"); }
@Override public void query() { System.out.println("查询了一个用户"); } }
|
3.代理角色
public class Proxy implements Rent{ private Host host;
public Proxy() { }
public Proxy(Host host) { this.host = host; }
@Override public void rent() { host.rent(); seeHouse; fare; hetong; }
public void seeHouse(){ System.out.println("中介带你看房"); }
public void fare(){ System.out.println("收中介费"); }
public void hetong(){ System.out.println("签租赁合同"); } }
public class UserServiceProxy implements UserService{
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) { this.userService = userService; }
@Override public void add() { log("add"); userService.add();
}
@Override public void delete() { log("delete"); userService.delete(); }
@Override public void update() { log("update"); userService.update(); }
@Override public void query() { log("query"); userService.query(); }
public void log(String msg){ System.out.println("使用了"+msg+"方法"); } }
|
4.客户端访问代理角色
public class Client { public static void main(String[] args) { Host host = new Host(); Proxy proxy = new Proxy(host);
proxy.rent(); } }
public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy =new UserServiceProxy(); proxy.setUserService(userService); proxy.add(); } }
|
代理模式的好处:
- 可以使真实角色的操作更加纯粹! 不用去关注一些公共的业务
- 公共业务就交给角色! 实现业务分工
- 公共业务发生拓展的时候,方便集中管理
缺点:
- 一个真实角色就会产生一个代理角色; 代码量翻倍 ~ 开发效率会变低
动态代理 – (底层:反射)
- 动态代理角色和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口 – JDK 代理 [使用]
- 基于类:cglib
- java字节码实现:JAVAssist
需要了解两个类: Proxy 代理 , InvocationHdandler
动态代理的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共也就就交给代理角色!实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
复用静态代理代码2
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) { this.target = target; }
public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(target, args); logcc(method.getName()); return result; }
public void logcc(String msg){ System.out.println("执行了"+msg+"方法"); }
}
|
public class Client { public static void main(String[] args) {
UserServiceImpl userService=new UserServiceImpl();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);
UserService proxy = (UserService) pih.getProxy(); proxy.add(); }
}
|
AOP

AOP 在Spring中的作用
- 横切关注点:垮越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…
- 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类【Log】
- 通知(Ad小ice):切面必须要完成的工作。即,它是类中的一个方法。【Log中的方法】
- 目标(Target):被通知对象
- 代理(Proxy):向目标对象应用通知之后创建的对象
- 切入点(PointCut):切面通知执行的“地点”的定义。
- **连接点(JointPoint)**:与切入点匹配的执行点。

SpringAOP中,通过 Advicec 定义横切逻辑,Spring中支持5种类型的Advice

即Aop 在不改变原有代码的情况下,去增加新的功能
使用Spring实现Aop
【重点】使用AOP织入,需要导入一个依赖包
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> </dependency> </dependencies>
|
方式一:使用Spring的API接口
public class Log implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
} }
|
- AfterReturningAdvice:带返回的后置通知
public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue); } }
|
public interface UserService { public void add(); public void delete(); public void update(); public void selete(); }
|
public class UserServiceImpl implements UserService{
@Override public void add() { System.out.println("增加了一个用户"); }
@Override public void delete() { System.out.println("删除了一个用户");
}
@Override public void update() { System.out.println("更新了一个用户");
}
@Override public void selete() { System.out.println("查询了一个用户"); } }
|
- applicationContext.xml配置文件织入AOP
- 配置AOP: 导入AOP的约束:< aop:config >< /aop:config >
- 定义切入点
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.chen.service.UserServiceImpl"/> <bean id="log" class="com.chen.log.Log"/> <bean id="afterLog" class="com.chen.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.chen.service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
|
public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService"); userService.add(); } }
|
方式二:自定义来实现AOP【主要是切面定义】
public class DiyPointCut { public void before(){ System.out.println("-------方法执行前-------"); } public void after(){ System.out.println("-------方法执行后-------"); } }
|
- applicationContext.xml配置文件织入AOP
. <bean id="diy" class="com.chen.diy.DiyPointCut"/> <aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.chen.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
|
方式三:使用注解实现

切面类
前置通知:**@Before** :@Before(“execution(类的方法及属性)”)
最终通知**@After** :@After(“execution(类的方法及属性)”)
后置通知**@AfterReturning** :@After(“execution(类的方法及属性)”)
异常通知
@Around("execution(类的方法及属性)")
|
@Aspect public class AnnotationPointCut {
@Before("execution(* com.chen.service.UserServiceImpl.*(..))") public void before(){ System.out.println("=========方法执行前========="); }
@After("execution(* com.chen.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=========方法执行后========="); }
@Around("execution(* com.chen.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("=========环绕前========="); Signature signature= joinPoint.getSignature(); System.out.println(signature); Object proceed = joinPoint.proceed();
System.out.println("proceed:"+proceed);
System.out.println("=========环绕后=========");
} }
|
执行结果:

- applicationContext.xml配置文件织入AOP
<bean id="annotationPointCut" class="com.chen.diy.AnnotationPointCut"/> <!-- 开启注解支持 JDK(默认:proxy-target-class="true") --> <aop:aspectj-autoproxy/>
|
Boot中
- controller所有的方法执行的时候,都会被织入动作
@Aspect @Component public class myAdvice { private Logger logger = LoggerFactory.getLogger(myAdvice.class);
@Pointcut(value = "execution( * com.example.spring09aopboot.controller.*.*(..))") public void myPointcut(){
} @Around("myPointcut()") public Object myLogger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { String className = proceedingJoinPoint.getTarget().toString(); String methodName = proceedingJoinPoint.getSignature().getName(); Object[] args = proceedingJoinPoint.getArgs(); ObjectMapper mapper = new ObjectMapper(); System.out.println("切面:执行前=============类:"+className+"---方法名:"+methodName+"---参数名:"+mapper.writeValueAsString(args)); Object proceed = proceedingJoinPoint.proceed(); System.out.println("切面:执行后=============类:"+className+"---方法名:"+methodName+"---参数名:"+mapper.writeValueAsString(args)); return proceed; } }
|
整合Mybatis
步骤:
1.导入相关jar包
- junit
- mybatis
- mysql数据包
- spring相关的
- aop织入
- mybatis-spring【new】
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.8.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> </dependencies>
|
2.编写配置文件
3测试
Mybatis
1.编写实体类
2.编写核心配置文件
3.编写接口
4.编写Mapper.xml
5.测试
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sessionFactory.openSession(true);
|
Mybatis-Spring
第一种整合
1、编写数据源配置
jdbc
曾经在在 mybatis-config.xml 编写
<!--引入外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
<environments default="development"><!--环境-->
<environment id="development">
<transactionManager type="JDBC"/><!--事务管理-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
- 现在 **spring-dao.xml** (spring和mybtais整合配置文件中)编写
```xml <!-- 固定写法 1~3 --> <?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.关联数据库配置文件--> <context:property-placeholder location="classpath:db.properties"/>
<!--2.连接池 dbcp:半自动化操作,不能自动连接 (Spring自带) c3pB:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中!) (需要导包) --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
|
2、sqlSessionFactory
曾经在Mybatis中编写
3、sqlSessionTemplate
4、需要给接口加实现类
public interface UserMapper { List<User> selectUser(); }
public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; }
public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } }
|
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.chen.mapper.UserMapper"> <select id="selectUser" resultType="User"> select * from mybatisb.user </select>
</mapper>
|
5、将自己写的实现类,注入到Spring中
<bean id="userMapper" class="com.chen.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean>
|
6、测试使用即可
public void selectUser(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper",UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
|
第二种整合
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
} }
|
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisb?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>
<!-- SqlSessionFactory:--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource"/> <!-- 绑定Mybatis配置文件 --> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!--绑定接口--> <property name="mapperLocations" value="classpath:com/chen/mapper/*.xml"/> </bean>
<!---------------------------------不需要配置---------------------------------> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!----------------------------------------------------------------------------> <bean id="userMapper2" class="com.chen.mapper.UserMapperImpl2"> <!-- 直接注入sqlSessionFactory--> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
|
总结

- 导依赖(注意maven资源过滤问题)
- pojo
- 接口
- 接口.xml(SQL)
- Mybatis配置,①mybatis-config.xml(编写settings和别名typeAliases) ②整合配置spring-dao.xml,最后在Spring中(applicationContext.xml)引用
- 接口实现类
- 接口实现类注入到Spring中
- 通过Spring注册
声明式事务
1、回顾事务
- 把一组业务当成一个业务来做;要么都成功,要么都失败!
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!
- 确保完整性和一致性;
事务ACID原则:
2、spring中的事务管理器

- 在一个方法中,实现查询,更新,删除,如果删除出现异常,但查询和更新都执行成功了,理论应该回滚
- 一个错误全部回滚,全对提交事务
<?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:aop="http://www.springframework.org/schema/aop" xmlns:contex="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="tranasctionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource"/> </bean>
<tx:advice id="txAdvice" transaction-manager="tranasctionManager">
<tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
<aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.chen.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
|
事务失效


