spring入门总结
- 一、spring介绍
- 1、spring是什么
- 2、理念:
- 3、Spring优点:
- 4、缺点
- 5、主要内容:
- 二、IOC&DI
- 1、使用IOC创建对象的三种方法
- a、无参构造方法创建
- b、通过有参构造方法来创建
- c、通过工厂方法来创建对象
- 2、配置文件详解
- 3、依赖注入DI
- 4、bean的作用域和自动装配
- 5、静态代理
- 6、动态代理
- 三、AOP
- 1、使用spring实现aop的方式
一、spring介绍
1、spring是什么
spring: 春天; --给软件行业带来了春天。
Spring是一个 轻量级的DI和AOP容器框架。
说它轻量级有一大部分原因是相对与EJB的(虽然本人从没有接触过EJB的应用),重要的是,Spring是非侵入式的(所谓非侵入式就是远程调试 而不植入,spring不再用new的方式来创建对象,而是使用依赖注入的方式),基于spring开发的应用一般不依赖于spring的类。
2、理念:
使现有技术更加实用。本身是大杂烩整合现有的框架技术。
3、Spring优点:
- 使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑
- 可以提供众多服务,事务管理,WS等。
- AOP的很好支持,方便面向切面编程。
- 对主流的框架提供了很好的集成支持,如hibernate,Struts2,JPA等
- Spring DI机制降低了业务对象替换的复杂性。
- Spring属于低侵入,代码污染极低。
- Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部
方便解耦,简化开发:
Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理
IOC容器–控制反转:
Spring是个容器,因为它包含并且管理应用对象的生命周期和配置。
aop面向切面编程:
Spring提供面向切面编程,可以方便的实现对程序权限拦截、运行监控等功能。
对事物的支持:
如对象的创建、销毁、回调等
对框架的支持:
Spring作为一个框架,提供了一些基础功能,(如事务管理,持久层集成等),使开发人员更专注于开发应用逻辑。
。。。
4、缺点
- jsp中要写很多代码、控制器过于灵活,缺少一个公用控制器
- Spring不支持分布式,这也是EJB仍然在用的原因之一。
首先Spring 是一个框架,使用Spring并不代表代码质量的提高,就像盖房子选择用上海的地皮还是北京的地皮一样,房子质量与土地所在的城市无关,与房子的具体设计方案和选料有关。
使用Spring 等框架可以简化很多基础性的工作,配置好后可以方便构建业务应用。
框架使用多了会有局限的感觉,像小鸟被套在笼子里,无法飞出去,虽然在笼子里面吃喝不愁。目前编程的门槛越来越低,诸多开源框架广泛传播,几乎没有什么技术门槛,会配置就会编程,而一个好的DBA对软件性能会有很大提高,软件的核心逻辑最终会转移到对数据库的操作上
5、主要内容:
二、IOC&DI
控制反转IOC(inversion of control) 和依赖注入DI(Dependency Injection) 一个概念,具体的讲,当一个角色需要另外一个角色协助的时候,在传统的程序设计中,通常有调用者来创建被调用者的实例。但是在spring中创建被调用者将不再有调用者完成,因此叫控制反转。创建被调用对象有Spring来完成,在容器实例化对象的时候主动的将被调用者(或者说它的依赖对象)注入给调用对象,因此又叫依赖注入。
特点:
对象由原来程序本身创建,变为了程序接收对象。
程序猿主要精力集中于业务实现。
实现了service和dao的解耦工作。service层和dao层实现了分离,没有直接的依赖关系。
如果dao的实现发生改变,应用程序本身不用改变。
下面创建第一个实例:
准备工作: idea配置
现在很多教程的都是MyEclipse编程,可能本人比较懒,所以直接用idea
创建Maven,创建一个web模板:
选好文件存放位置。
2020版本的idea,不用手动导包,进去它直接执行导包操作。
等待一段时间后~
resources下创建一个xml,名字自己取
OK,现在编写第一个spring程序
写一个xml,一般他会自动生成,只要把第6、7行写进去就行了
<?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就是java对象 由spring来创建管理--><bean name="hello" class="spring02_ioc.test.bean.hello"><property name="name" value="昀离君"/></bean>
</beans>
写一个hello.java
package spring02_ioc.test.bean;public class hello {public hello(){System.out.println("hello被创建");}private String name;public void setName(String name){this.name = name;}public void show(){System.out.println("hello" +name);}
}
写一个test.java
package spring02_ioc.test;import spring02_ioc.test.bean.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {//解析applicationContext.xml文件生成相应的bean对象ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");hello hello = (hello)context.getBean("hello");hello.show();}
}
运行test,得到下面结果:
那么,接下来思考?
hello对象是谁创建的?
hello对象属性是怎样设置的?
hello对象是由spring容器创建的。
hello对象属性是spring容器来设置的。
这个过程就叫控制反转:
控制内容: 指谁来控制对象的创建;传统的应用程序对象的创建是由程序本身控制的。使用spring后,是由spring来创建对象的。
反转: 正转指程序来创建对象,反转指程序本身不创建对象,而变为被动的接收对象。
总结: 以前对象是由程序本身来创建,使用spring后,程序变为被动接收spring创建好的对象。
控制反转 == 依赖注入
1、使用IOC创建对象的三种方法
a、无参构造方法创建
User.java
package spring04_ioc3.vo;public class User {public User(){System.out.println("User的无参构造方法");}private String name;public void setName(String name) {this.name = name;}public void show(){System.out.println("name" + name);}
}
bean.xml
<bean id="user" class="spring04_ioc3.vo.User"><property name="name" value="昀离君"></property></bean>
Test.java
package spring04_ioc3.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring04_ioc3.vo.User;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User)ac.getBean("user");user.show();}
}
b、通过有参构造方法来创建
User.java
package spring04_ioc3.vo;public class User {public User(String name){super();this.name = name;}private String name;public void show(){System.out.println("name" + name);}
}
bean.xml配置(有三种)
-
根据参数的下标来设置
<bean id="user" class="spring04_ioc3.vo.User"><!--index指构造方法参数下标从0开始--><constructor-arg index="0" value="小昀离君"/> </bean>
-
根据参数名称来设置
<bean id="user" class="spring04_ioc3.vo.User"><!--name指参数名--><constructor-arg name="name" value="小昀离君"/> </bean>
-
根据参数类型设置
<bean id="user" class="spring04_ioc3.vo.User"><!--name指参数名--><constructor-arg type="java.lang.String" value="小昀离君"/> </bean>
Test.java
package spring04_ioc3.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring04_ioc3.vo.User;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User)ac.getBean("user");user.show();}
}
c、通过工厂方法来创建对象
-
静态工厂
UserFactory.javapublic class UserFactory {public static User newIstance(String name){return new User(name);} }
bean.xml配置
<bean id="user" class="spring04_ioc3.factory.UserFactory" factory-method="newIstance"><constructor-arg index="0" value="凡一"/> </bean>
-
动态工厂
UserDynamicFactory.javapublic class UserDynamicFactory {public User newIstance(String name){return new User(name);} }
bean.xml配置
<bean id="userFactory" class="spring04_ioc3.factory.UserDynamicFactory"/><bean id="user" factory-bean="userFactory" factory-method="newIstance"><constructor-arg index="0" value="凡一"/> </bean>
2、配置文件详解
-
alias:为bean设置别名,可以设置多个别名
<!--设置别名--><alias name="user" alias="user1 "/>
-
bean的配置
id是bean的标识符 要唯一 如果没有配置id,name默认标识符
如果配置了id,又配置了name,那么name是别名
name可以设置多个别名 分隔符可以是空格、逗号、分好等
class是bean的全限定名= 包名 + 类名
如果不配置id,和name 那么可以根据applicationContext.getBean(Class)获取对象
<!--id是bean的标识符 要唯一 如果没有配置id,name默认标识符如果配置了id,又配置了name,那么name是别名name可以设置多个别名 分隔符可以是空格、逗号、分好等class是bean的全限定名= 包名 + 类名如果不配置id,和name 那么可以根据applicationContext.getBean(Class)获取对象--><bean id="h1" name="hello h2,h3;h4" class="spring02_ioc.test.bean.hello"><property name="name" value="小凡一"/></bean>
-
团队合作通过import来实现
<import resource="entity.xml"/>
3、依赖注入DI
-
依赖注入—dependency injection
依赖: 指bean对象创建依赖容器,bean对象的依赖资源
注入: 指bean对象依赖的资源由容器来设置和装配 -
spring注入—构造器注入
见IOC创建对象 -
spring注入——setter注入 (重点)
要求被注入的属性必须有set方法。set方法的方法名由set+属性首字母大写。如果属性是Boolean 没有get方法 会返回is-
常量注入
<bean id="student" class="spring05_di.vo.Student"><property name="name" value="小小凡一"></property></bean>
-
bean注入
<bean id="addr" class="spring05_di.vo.Address"/><bean id="student" class="spring05_di.vo.Student"><property name="name" value="小小凡一"></property><property name="addr" ref="addr"/></bean>
-
数组注入
<property name="books"><array><value>傲慢与偏见</value><value>战争与和平</value><value>盗梦者</value></array> </property>
-
list注入
<property name="hobbies"><list><value>羽毛球</value><value>乒乓球</value><value>篮球球</value><value>台球</value></list></property>
-
map注入
<property name="cards"><map><entry key="中国银行" value="4541534455"/><entry><key><value>建设银行</value></key><value>1531534631637</value></entry></map></property>
-
set注入
<property name="games"><set><value>lol</value><value>dota</value><value>王者荣耀</value><value>吃鸡</value></set></property>
-
null注入
<property name="wife"><null/></property>
-
Properties注入
需要在头文件中加入:xmlns:p="http://www.springframework.org/schema/p"
<property name="info"><props><prop key="学号">202008092355</prop><prop key="sex">男</prop><prop key="name">凡一</prop></props></property>
-
p命名空间注入
<!--p命名空间注入 属性依然要设置set方法--><bean id="user" class="spring05_di.vo.User" p:name="小朋友" p:age="12"/>
-
c命名空间注入
需要在头文件中加入:xmlns:c="http://www.springframework.org/schema/c"
<!--c命名空间注入要求有对应参数的构造方法--><bean id="u1" class="spring05_di.vo.User" c:name="Elias" c:age="2000"/>
-
文件总合如下:
student.java
package spring05_di.vo;import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;public class Student {private String name;private Address addr;private String[] books;private List<String> hobbies;private Map<String, String> cards;private Set<String> games;private String wife;private Properties info;public void setName(String name) {this.name = name;}public void setAddr(Address addr) {this.addr = addr;}public void setBooks(String[] books) {this.books = books;}public void setHobbies(List<String> hobbies) {this.hobbies = hobbies;}public void setCards(Map<String, String> cards) {this.cards = cards;}public void setGames(Set<String> games) {this.games = games;}public void setWife(String wife) {this.wife = wife;}public void setInfo(Properties info) {this.info = info;}public void show(){System.out.println("name= " + name + " address=" + addr.getAddress());System.out.print("books: ");for (int i = 0; i < books.length; i++){System.out.print(books[i] + " ");}System.out.println();System.out.println("hobbies= " + hobbies);System.out.println("cards= " + cards);System.out.println("games= " + games);System.out.println("wife= " + wife);System.out.println("info= " + info);}
}
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"xmlns:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--bean就是java对象 由spring来创建管理--><bean id="addr" class="spring05_di.vo.Address"><property name="address" value="广东河源"></property></bean><bean id="student" class="spring05_di.vo.Student"><property name="name" value="小小凡一"/><property name="addr" ref="addr"/><property name="books"><array><value>傲慢与偏见</value><value>战争与和平</value><value>盗梦者</value></array></property><property name="hobbies"><list><value>羽毛球</value><value>乒乓球</value><value>篮球球</value><value>台球</value></list></property><property name="cards"><map><entry key="中国银行" value="4541534455"/><entry><key><value>建设银行</value></key><value>1531534631637</value></entry></map></property><property name="games"><set><value>lol</value><value>dota</value><value>王者荣耀</value><value>吃鸡</value></set></property><property name="wife"><null/></property><property name="info"><props><prop key="学号">202008092355</prop><prop key="sex">男</prop><prop key="name">凡一</prop></props></property></bean><!--p命名空间注入 属性依然要设置set方法--><bean id="user" class="spring05_di.vo.User" p:name="小朋友" p:age="12"/><!--c命名空间注入要求有对应参数的构造方法--><bean id="u1" class="spring05_di.vo.User" c:name="Elias" c:age="2000"/>
</beans>
Address.java
package spring05_di.vo;public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
User.java
package spring05_di.vo;public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
Test.java
package spring05_di.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring05_di.vo.Student;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");Student stu = (Student)ac.getBean("student");stu.show();}
}
Tesxt1.java
package spring05_di.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring05_di.vo.User;public class Test1 {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) ac.getBean("u1");System.out.println(user);}
}
4、bean的作用域和自动装配
bean的作用域:
scope指bean的作用域,在配置bean时,由scope来配置bean的作用域
singleton单例: 整个容器中只有一个对象实例 默认是单例
prototype原型 : 每次获取bean都产生一个新的对象
request: 每次请求时创建一个新的对象
session: 在会话的范围内是一个对象
global session: 只在portlet下有用,表示是application
application: 在应用范围中一个对象
书写格式示例:
<bean id="addr" class="spring05_di.vo.Address" scope="prototype">
注意: 在整合strut2和spring时,需要将action设为 scope=“prototype”。
自动装配——简化spring配置文件:
在配置bean时,可以配置bean的autowire属性,用于指定装配类型。
no : 不使用自动装配
ByName : 根据名称去查找相应的bean,如果有则装配上
byType : 根据类型进行自动装配 不用管bean的id,但是同一种类型的bean只能有一个 建议慎用
constructor: 当通过构造器注入实例化bean时 使用byType的方式装配构造方法
书写格式示例:
<bean id="addr" class="spring05_di.vo.Address" autowire="byName"/>
可以配置全局的自动装配类型,在头部添加default-autowire
示例:
<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" default-autowire="byName">
推荐不使用自动装配,使用annotation
5、静态代理
- 静态代理的角色分析:
抽象角色----一般使用接口或者抽象类来实现。
真实角色----被代理的角色。
代理角色----代理真实角色,代理真实角色后一般会做一些附属操作。
客户 ----使用代理角色来进行一些操作。
图例:
-
代码实现
Rent.java—抽象角色
public interface Rent {public void rent(); }
Host.java—真实角色
public class Host implements Rent{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;}public void setHost(Host host) {this.host = host;}//租房public void rent(){seehouse();host.rent();fare();}//看房private void seehouse(){System.out.println("带房客看房");}//收中介费private 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();} }
结果:
-
使用静态代理的好处:
- 使得真实角色处理的业务更加纯粹,不再去关注一些公共的事情。
- 公共的业务由代理来完成----实现业务的分工
- 公共业务发生扩展时变得更加集中和方便
缺点:
类多了----多了代理类。工作量变大了。开发效率变低了
6、动态代理
-
动态代理和静态代理的角色是一样的。
-
动态代理的代理类是动态生成的。
-
分为两类,一类基于接口动态代理和基于类的动态代理
a.基于接口动态代理----jdk动态代理
b.基于类的动态代理----cglib
现在用javassist来生成动态代理。javassist介绍:
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。
关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。 -
jdk动态代理----Proxy类和InvocationHandler接口
InvocationHandler 是代理实例的 调用处理程序 实现的接口。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的invoke方法。
invoke(Object proxy, Method method, Object[] args) //在代理实例上处理方法调用并返回结果
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
参数:
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的Method实例。Method对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 是包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为null。基本类型的参数被包装在适当基本包装器类(如java.lang.Integer 或java.lang.Boolean)的实例中。
返回:
从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为null并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出ClassCastException。
实现:
ProxyInvoationHandler.java
package spring08_dynamicproxy.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyInvoationHandler implements InvocationHandler {private Object target; //目标对象---真实对象public void setTarget(Object target) {this.target = target;}public void setRent(Rent rent) {this.target = rent;}/*** 生成代理类*/public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(), this);}/*** proxy是代理类* method 代理类的调用处理程序的方法对象*/@Overridepublic 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 methodName){System.out.println("执行" + methodName + "方法");}
}
Clinet.java
package spring08_dynamicproxy.dynamicproxy;import spring08_dynamicproxy.service.UserService;
import spring08_dynamicproxy.service.UserServiceImpl;public class Clinet {public static void main(String[] args) {UserService userService = new UserServiceImpl();ProxyInvoationHandler pih = new ProxyInvoationHandler();pih.setTarget(userService);UserService proxy = (UserService)pih.getProxy();proxy.add();}
}
UserService.java
package spring08_dynamicproxy.service;public interface UserService {public void add();public void update();public void delete();public void search();
}
UserService.java
package spring08_dynamicproxy.service;public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("增加用户");}@Overridepublic void update() {System.out.println("修改用户");}@Overridepublic void delete() {System.out.println("删除用户");}@Overridepublic void search() {System.out.println("查询用户");}}
注意:
一个动态代理一般代理某一类业务,一个动态代理可以代理多个类。
三、AOP
AOP(aspect oriented programming): Spring对面向切面编程提供了强有力的支持,通过它让我们将业务逻辑从应用服务(如事务管理)中分离出来,实现了高内聚开发(所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。),应用对象只关注业务逻辑,不再负责其它系统问题(如日志、事务等)。Spring支持用户自定义切面。
面向切面编程是面向对象编程的有力补充。面向对象编程将程序分成各个层次的对象,面向切面的程序将运行过程分解成各个切面。AOP是从运行程序的角度去考虑程序的结构,提取业务处理过程的切面,OOP是静态的抽象,AOP是动态的抽象,是对应用执行过程的步骤进行抽象,从而获得步骤之间的逻辑划分。
-
aop在spring中的作用
- 提供声明式服务(声明式事务)
- 允许用户实现自定义切面
-
aop:在不改变原有代码的情况下,增加新的功能。
传统的编程模式:
aop的编程模式:
-
aop的好处:
a、使用真实角色处理的业务更加纯粹,不再去关注一些公共的事情。
b、公共的业务由代理来完成-----实现业务的分工
c、公共业务发生扩展时变得更加集中和方便 -
名词解释:
关注点: 增加的某个业务。如日志、安全、缓存、事务等。
切面(Aspect): 一个关注点的模块化
通知(Advice): 在切面的某个特定的连接点上执行的动作
织入(Weaving): 把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象
1、使用spring实现aop的方式
第一种实现方式-----通过springAPI来实现。
log.java—前置通知
package spring09_aop1.log;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class log implements MethodBeforeAdvice {public void log(){}/*** @param method 被调用方法对象* @param args 被调用的方法参数* @param target 被调用的方法目标对象*/@Overridepublic void before(Method method, Object[] args, Object target)throws Throwable {System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行");}}
AfterLog.java
package spring09_aop1.log;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class AfterLog implements AfterReturningAdvice {/*** 目标方法执行后执行的通知** @param returnValue 返回值* @param method 被调用的方法对象* @param args 被调用的方法对象的参数* @param target 被调用的方法对象的目标对象* @throws Throwable*/@Overridepublic void afterReturning(Object returnValue, Method method,Object[] args, Object target)throws Throwable {System.out.println(target.getClass().getName() + "的" + method.getName() + "被成功执行,返回值是:" + returnValue);}}
目标类
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("增加用户");}@Overridepublic void update() {System.out.println("修改用户");}@Overridepublic void delete() {System.out.println("删除用户");}@Overridepublic void search() {System.out.println("查询用户");}}
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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="userService" class="spring09_aop1.impl.UserServiceImpl"/><bean id="log" class="spring09_aop1.log.log"/><bean id="afterLog" class="spring09_aop1.log.AfterLog"/><aop:config><aop:pointcut expression="execution(* spring09_aop1.service.*.*(..))" id="pointcut"/><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config></beans>
测试类:
public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService)ac.getBean("userService");userService.add();}}
aop的重要性:
spring aop就是将公共业务(如日志、安全等)和领域业务结合。当执行领域业务时将会把公共业务加进来。实公共业务的重复利用。领域业务更纯粹,程序猿专注于领域业务。其本质还是动态代理。
第二种方式实现aop:自定义类来实现
log.java
public class log {public void before(){System.out.println("---------方法执行前---------");}public void after(){System.out.println("---------方法执行前---------");}}
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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="UserService" class="spring10_aop2.impl.UserServiceImpl"/><bean id="log" class="spring10_aop2.log.log"/><aop:config><aop:aspect ref="log"><aop:pointcut id="pointcut" expression="execution(* spring10_aop2.impl.*.*(..))"/><aop:before method="before" pointcut-ref="pointcut"/><aop:after method="after" pointcut-ref="pointcut"/></aop:aspect></aop:config></beans>
UserServiceImpl.java
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("---------添加用户数据----------");}@Overridepublic void delete() {System.out.println("----------删除用户数据----------");return;}}
UserService.java
public interface UserService {public void add();public void delete();}```Test.java```javapublic class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService)ac.getBean("UserService");userService.delete();}}
第三种实现方法—通过注解来实现
log.java
package spring11_aop3.log;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;@Aspect
public class log {@Before("execution(* spring11_aop3.impl.*.*(..))")public void before(){System.out.println("---------方法执行前---------");}@After("execution(* spring11_aop3.impl.*.*(..))")public void after(){System.out.println("---------方法执行后---------");}@Around("execution(* spring11_aop3.impl.*.*(..))")public Object aroud(ProceedingJoinPoint jp) throws Throwable {System.out.println("环绕前");System.out.println("签名" + jp.getSignature());//执行目标方法Object result = jp.proceed();System.out.println("环绕后");return result;}
}
如果idea输入注解@Aspect时,出现错误,原因是因为注解包没导进去,在pom.xml中加入下列这段(然后等一会儿,让idea下载完):
<!-- http://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency><!-- http://mvnrepository.com/artifact/cglib/cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.2</version></dependency>
配置文件:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="UserService" class="spring11_aop3.impl.UserServiceImpl"/><bean id="log" class="spring11_aop3.log.log"/><aop:aspectj-autoproxy/>
</beans>
UserService.java
package spring11_aop3.service;public interface UserService {public void add();public void delete();
}
UserServiceImpl.java
package spring11_aop3.impl;import spring11_aop3.service.UserService;public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("---------添加用户数据----------");}@Overridepublic void delete() {System.out.println("----------删除用户数据----------");return;}}
Test.java
package spring11_aop3.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring11_aop3.service.UserService;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService)ac.getBean("UserService");userService.delete();}
}
未完待续…