分析实现
dao层:使用不同的接口完成对不同数据库的操作
public interface UserDao {
void gerUser();
}
public class UserDaoImpl implements UserDao {
@Override
public void gerUser() {
System.out.println("默认获取用户的数据");
}
}
public class UserDaoMysqlImpl implements UserDao {
@Override
public void gerUser() {
System.out.println("使用mysql存储数据");
}
}
public class UserDaoOracleImpl implements UserDao {
@Override
public void gerUser() {
System.out.println("使用oracle存储数据");
}
}
业务层(Service):调用dao层方法
public interface UserService {
void getUser();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 传统方法要使用oracle或者mysql数据库都需要更改源代码,这就违反了
// 开闭原则:
// 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
// private UserDao userDao = new UserDaoMysqlImpl();
// private UserDao userDao = new UserDaoOracleImpl();
//这里使用set来动态实现方法的调用而不需要改变原业务层代码,修改一次代码的成本大
//传统方法的程序是主动创建对象,控制权在程序员手上
//使用set注入后,程序不再具有主动性,而是变成了被动接受对象
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
@Override
public void getUser() {
userDao.gerUser();
}
}
测试类:
public class MyTest {
public static void main(String[] args) {
//用户实际调用的是业务层,dao层不需要接触
UserService userService = new UserServiceImpl();
//使用set完成对象的注入,不像传统方式要调用不同的数据库要手动更改业务层的代码
((UserServiceImpl)userService).setUserDao(new UserDaoMysqlImpl());
userService.getUser();
}
}
控制反转IOC(Inversion Of Control)是一种设计思想,DI(依赖注入)只是IOC的一种实现方式,可以认为所谓的控制反转就是获得依赖对象的方式转变了
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.9version>
dependency>
实体类:
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
编写我们的spring文件 , 这里我们命名为beans.xml(官方命名为applicationContext.xml,这里随便定义都行)
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="com.golven.pojo.Hello">
<property name="str" value="Spring">property>
bean>
beans>
测试:
public class MyTest {
public static void main(String[] args) {
//实例化容器,凡是通过xml文件配置spring都要这条语句,获取Spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在Spring中管理了,我们要使用直接去里面取出来就行
Hello hello = (Hello)context.getBean("hello");
System.out.println(hello.toString());
}
}
在案例中,hello对象是由spring创建的,hello对象的属性是由spring容器设置的
这个过程就叫控制反转
- 控制:谁来控制对象的创建,传统应用程序的对象是由应用程序本身控制创建的,使用spring后,对象是由spring创建的
- 反转:程序本身不创建对象,而变成被动接收对象
依赖注入 : 就是利用set方法来进行注入的,如果将实体类中的set方法删去,则无法注入
实体类:
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public User(){
System.out.println("User的无参构造");
}
}
beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.golven.pojo.User">
<property name="name" value="golven"></property>
</bean>
</beans>
javapublic class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//注意到这里getBean时Spring采用无参构造创建对象
User user = (User)context.getBean("user");
System.out.println(user.toString());
}
}
第一种,采用下标对应参数
<bean id="user" class="com.golven.pojo.User">
<constructor-arg index="0" value="我干">constructor-arg>
bean>
第二种,通过数据类型创建
<bean id="user" class="com.golven.pojo.User">
<constructor-arg type="java.lang.String" value="搞快点">constructor-arg>
bean>
第三种,通过参数名创建
<bean id="user" class="com.golven.pojo.User">
<constructor-arg name="name" value="我命由我不由天">constructor-arg>
bean>
总结,在配置文件加载的时候,IOC中的对象就全部都创建了
<alias name="user" alias="userNew">alias>
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
bean>
这个import一般用于团队开发使用,它可以将多个配置文件导入合并为一个配置文件
假设现在团队中有多个人开发,这三个人有不同的类,不同的类需要注册在不同的bean中,我们可以利用import将所有的beans.xml合并为一个总的
applicationContext.xml
<import resource="beans.xml">import>
前面说过了
要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .
实体类:
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbies=" + hobbies +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
<bean id="student" class="com.golven.pojo.Student">
<property name="name" value="golven">property>
bean>
<bean id="add" class="com.golven.pojo.Address">
<property name="address" value="荆州">property>
bean>
<bean id="student" class="com.golven.pojo.Student">
<property name="name" value="golven">property>
<property name="address" ref="add">property>
bean>
<bean id="student" class="com.golven.pojo.Student">
<property name="books">
<array>
<value>西游记value>
<value>红楼梦value>
<value>水浒传value>
array>
property>
bean>
<bean id="student" class="com.golven.pojo.Student">
<property name="hobbies">
<list>
<value>唱歌value>
<value>跳舞value>
list>
property>
bean>
<bean id="student" class="com.golven.pojo.Student">
<property name="card">
<map>
<entry key="中国移动" value="123456789">entry>
<entry key="中国联通" value="155555555">entry>
map>
property>
bean>
<bean id="student" class="com.golven.pojo.Student">
<property name="games">
<set>
<value>LOLvalue>
<value>三国杀value>
set>
property>
bean>
<property name="wife"><null/>property>
<property name="info">
<props>
<prop key="学号">1705110119prop>
<prop key="性别">男prop>
props>
property>
测试类:
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student)context.getBean("student");
System.out.println(student.getName());
System.out.println(student.getAddress().getAddress());
System.out.println(Arrays.toString(student.getBooks()));
System.out.println(student.getHobbies().toString());
System.out.println(student.getCard());
System.out.println(student.getGames());
System.out.println(student.getWife());
System.out.println(student.getInfo());
}
}
实体类:
public class User {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>
发现问题:爆红了,刚才我们没有写有参构造!
解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入!
测试代码:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
//有User.class就不用强转
User user = context.getBean("user",User.class);
System.out.println(user.toString());
}
<bean id="user" class="com.golven.pojo.User" p:name="golven" p:age="21" scope="singleton">bean>
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
在spring中有三种装配方式:
实体类:
public class Person {
private String name;
private Cat cat;
private Dog dog;
public Person(String name, Cat cat, Dog dog) {
this.name = name;
this.cat = cat;
this.dog = dog;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
public class Cat {
public void shout(){
System.out.println("喵喵");
}
}
public class Dog {
public void shout(){
System.out.println("汪汪");
}
}
spring配置文件:
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.golven.pojo.Dog">bean>
<bean id="cat" class="com.golven.pojo.Cat">bean>
<bean id="person" class="com.golven.pojo.Person">
<property name="name" value="小哪吒">property>
<property name="cat" ref="cat">property>
<property name="dog" ref="dog">property>
bean>
beans>
测试:
@Test
public void testMethodAutowire() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person person =context.getBean("person",Person.class);
person.getCat().shout();
person.getDog().shout();
}
<bean id="dog" class="com.golven.pojo.Dog">bean>
<bean id="cat" class="com.golven.pojo.Cat">bean>
<bean id="person" class="com.golven.pojo.Person" autowire="byName">
<property name="name" value="小哪吒">property>
bean>
<bean id="dog" class="com.golven.pojo.Dog">bean>
<bean id="cat" class="com.golven.pojo.Cat">bean>
<bean id="person" class="com.golven.pojo.Person" autowire="byType">
<property name="name" value="小哪吒">property>
bean>
小结:
byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性类型一致
要使用注解须知:
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
beans>
@Autowired注解
@Autowired是按类型(byType)自动转配的,不支持byName匹配。
直接在类中的属性上使用,也可以在set方法上使用
使用@Autowired我们可以不用编写set方法,前提是这个自动装配属性在IOC容器中存在,且符合byName
tips:
@Nullable 字段标记了这个注解,说明这个字段可以为空
@Autowired(required=false) 说明: false,对象可以为null;true,对象必须存对象,不能为null。
测试代码:
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
@Qualifier注解
测试:
配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!
<bean id="dog1" class="com.kuang.pojo.Dog"/>
<bean id="dog2" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>
没有加Qualifier测试,直接报错
在属性上添加Qualifier注解
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
@Resource注解
实体类:
public class User {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}
beans.xml
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>
测试结果成功
配置文件2:beans.xml , 删掉cat2
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
实体类只保留注解
@Resource
private Cat cat;
@Resource
private Dog dog;
结果:OK
结论:先进行byName查找,失败;再进行byType查找,成功。
@Autowired和@Resource注解的区别
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过byType的方式实现,而且必须要求这个对象存在!
- @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两者都找不到则报错!
在spring4之后,想要使用注解形式,必须要引入aop的包
在配置文件中还应该引入context约束
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
之前我们都是使用bean标签在xml文件中注入,但是在实际开发中,我们一般都会使用注解
<context:component-scan base-package="com.golven.pojo"/>
@Component("user")
//相当于配置文件中
public class User {
public String name="golven";
}
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user", User.class);
System.out.println(user.name);
}
使用@Value注入属性,可以不用提供set方法,直接在直接名上添加@value(“值”)
@Component("user")
//相当于配置文件中
public class User {
@Value("golven")
//相当于配置文件中的
public String name;
}
@Component有几个衍生的注解,我们在web开发中,会按照mvc三层架构进行分层!
这四个注解的功能都是一样的,都是代表将某个类注册在Spring中装配Bean
@Controller("user")
@Scope("prototype")
public class User {
@Value("golven")
public String name;
}
小结:xml和注解
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己类使用不了,维护相对复杂
xml与注解的最佳实践:
- xml只用来管理bean
- 注解用来完成属性的注入
- 我们在是使用的过程中,只需要注意一个问题就是使注解生效
JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。
实体类:
//将这个类注入到IOC容器中
@Component
public class User {
@Value("GOLVEN")
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
新建一个config包,编写一个MyConfig配置类
@Configuration
//这里的@Configuration代表一个配置类,就相当于之前的xml配置文件
//这个也会在Spring容器中托管,注册到容器中,因为他本来就是一个Component
@ComponentScan("com.golven.pojo")
public class MyConfig {
//通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
//相当于之前xml文件中的bean标签
@Bean
public User getUser(){
return new User();
}
}
测试:
@Test
public void test(){
//使用AnnotationConfigApplicationContext获取到IOC容器
//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User getUser = context.getBean("getUser", User.class);
System.out.println(getUser.toString());
}
@Import(MyConfig2.class)
为什么要学习代理模式,因为AOP的底层机制就是代理模式
代理模式:
角色分析:
代码实现:
Rent.java 抽象角色
public interface Rent {
public void rent();
}
Host . java 即真实角色
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房屋出租");
}
}
Proxy.java 代理角色
public class Proxy implements Rent {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
//租房
@Override
public void rent() {
seeHouse();
host.rent();
fare();
}
//看房
public void seeHouse(){
System.out.println("看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
Client.java 客户
//客户类,一般客户都会去找代理!
public class Client {
public static void main(String[] args) {
//房东要租房
Host host = new Host();
//中介帮房东租房
Proxy proxy = new Proxy(host);
//客户找中介租房
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共也就交给了代理角色,实现了角色分工
- 公共业务发生扩展的时候,方便集中管理
- 在不改变原有代码的基础上做一些修改会更有优势,符合开闭原则,改动部分采用代理模式试错成本更小
缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低
需要了解两个类:
代码实现:
Rent.java 抽象角色
public interface Rent {
public void rent();
}
Host. java 即真实角色
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房屋出租");
}
}
ProxyInvocationHandler.java 动态生成代理角色
//等会我们会用这个动态代理类的处理程序自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理实例,并返回代理结果
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质就是使用反射机制实现的
Object result = method.invoke(rent, args);
return result;
}
}
Client.java
public class Client {
public static void main(String[] args) {
//真实的代理角色
Host host = new Host();
//代理角色:现在没有
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setRent(host);
//这里的proxy就是动态生成的,我们没有写
Rent proxy = (Rent) proxyInvocationHandler.getProxy();
proxy.rent();
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、
深化理解:
将上面的Rent变成Object就是通用的模板了
//等会我们会用这个动态代理类的处理程序自动生成代理类
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);
}
//处理代理实例,并返回代理结果
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过反射获取执行函数的名称
log(method.getName());
//动态代理的本质就是使用反射机制实现的
Object result = method.invoke(target, args);
return result;
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
public class Client {
@Test
public void Test01(){
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//设置要代理的对象
proxyInvocationHandler.setTarget(userService);
UserService proxy = (UserService)proxyInvocationHandler.getProxy();
proxy.add();
}
}
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译的方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中的一个特点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
提供声明式事务;允许用户自定义切面
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .
【important!】导入依赖
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
public interface UserService {
public void add();
public void delete();
public void query();
public void update();
}
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("查询用户");
}
}
使用spring原生的API配置环绕增强
public class Log implements MethodBeforeAdvice{
//method:要执行目标对象的方法
//objects:被调用的方法的参数
//Object:目标对象
@Override
public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"方法执行了");
}
}
public class AfterLog implements AfterReturningAdvice {
/**
*
* @param returnValue 返回值
* @param method 被调用的方法
* @param args 被调用的方法的对象的参数
* @param target 被调用的目标对象
* @throws Throwable
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+target.getClass().getName()+"的"+method.getName()+"方法,返回值:"+returnValue);
}
}
最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束 .
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="UserService" class="com.golven.service.UserServiceImpl">bean>
<bean id="Log" class="com.golven.Log.Log">bean>
<bean id="AfterLog" class="com.golven.Log.AfterLog">bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.golven.service.UserServiceImpl.*(..))">aop:pointcut>
<aop:advisor advice-ref="Log" pointcut-ref="pointcut">aop:advisor>
<aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut">aop:advisor>
aop:config>
beans>
测试:注意这里联想到代理模式
public class MyTest {
@Test
public void text01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口
UserService userService = context.getBean("UserService", UserService.class);
userService.add();
}
}
保持UserService,UserServiceImpl类不变
自己定义一个切入类
public class DiyLog {
public void before(){
System.out.println("--------在方法执行前---------");
}
public void after(){
System.out.println("-------在方法执行后--------");
}
}
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="UserService" class="com.golven.service.UserServiceImpl">bean>
<bean id="Log" class="com.golven.Log.Log">bean>
<bean id="AfterLog" class="com.golven.Log.AfterLog">bean>
<bean id="diy" class="com.golven.Diy.DiyLog"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="pointcut" expression="execution(* com.golven.service.UserServiceImpl.*(..))">aop:pointcut>
<aop:before method="before" pointcut-ref="pointcut">aop:before>
<aop:after method="after" pointcut-ref="pointcut">aop:after>
aop:aspect>
aop:config>
beans>
测试还是原代码
【主要是在xml文件中定义切面】
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.golven.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("=======在方法执行前========");
}
@After("execution(* com.golven.service.UserServiceImpl.*(..))")
public void After(){
System.out.println("==========在方法执行后===========");
}
@Around("execution(* com.golven.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("环绕前:");
//执行方法
Object proceed = pj.proceed();
System.out.println("环绕后:");
}
}
<bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.1.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.1.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.10version>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
@Data
public class User {
private int id;
private String name;
private String pwd;
}
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.golven.pojo">package>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?seSSL=true&useUnicode=true&characterEncoding=utf8">property>
<property name="username" value="root">property>
<property name="password" value="123456">property>
dataSource>
environment>
environments>
<mappers>
<package name="com.golven.mapper">package>
mappers>
configuration>
public interface UserMapper {
public List<User> selectUser();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.golven.mapper.UserMapper">
<select id="selectUser" resultType="User">
select * from user
select>
mapper>
@Test
public void test01() throws IOException {
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = build.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for(User u : users){
System.out.println(u);
}
}
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?seSSL=true&useUnicode=true&characterEncoding=utf8">property>
<property name="username" value="root">property>
<property name="password" value="123456">property>
bean>
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="configLocation" value="classpath:mybatis-config.xml">property>
<property name="mapperLocations" value="classpath:com/golven/mapper/*.xml">property>
bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="SqlSessionFactory">constructor-arg>
bean>
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSessionTemplate;
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
<bean id="userMapperImpl" class="com.golven.mapper.UserMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSession">property>
bean>
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapperImpl userMapperImpl = context.getBean("userMapperImpl", UserMapperImpl.class);
System.out.println(userMapperImpl.selectUser());
}
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
@Override
public List<User> selectUser() {
SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
<bean id="userMapperImpl2" class="com.golven.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="SqlSessionFactory">property>
bean>
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapperImpl2 userMapperImpl = context.getBean("userMapperImpl2", UserMapperImpl2.class);
System.out.println(userMapperImpl.selectUser());
}
第二种方式就不需要在UserMapperImpl中定义SqlSessionTemplate属性,直接getSession就能拿到SqlSession
事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。
事务四个属性ACID
事务的配置:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<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.golven.mapper.*.*(..))">aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut">aop:advisor>
aop:config>
为什么需要配置事务?