Spring
spring使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架
spring官方网址:https://spring.io
优点:
- 开源免费的框架
- 轻量级。非入侵式的框架
- 控制反转(IOC)、面向切面编程(AOP)
- 声明式事务的支持,对框架整合的支持
- 方便解耦,简化开发
Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)的框架
IOC理论推导
用户的需求可能会影响原来的代码,需要频繁修改代码,此时可以使用接口来实现动态值的输入。
//利用set实现动态值的输入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
-
之前程序是主动创建对象,控制权在程序员手上
-
使用set注入后,程序不在具有主动性,而是变成了被动的接受对象
这种思想,从本质上解决了问题,程序员不用再去管理对象的创建了,系统的耦合性那个大大降低,专注于业务的实现上。IOC的原型。
IOC本质:控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法。IOC是Spring框架的核心内容
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。采用XML方式配置文件的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)。
控制 : 谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转 : 程序本身不创建对象,而变成被动的接收对象.
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收.
实现不同的操作就不用再程序中去改动了,只需要在xmI配置文件中进行修改,所谓的IoC:对象由Spring来创建,管理,装配
Spring配置文件
1.Bean标签的基本配置
实用配置对象交由Spring来创建,将生成的对象添加到ioc容器中.
细节:默认情况下调用了当前类中的无参构造器,如果类中没有无参构造器,则不能创建对象.
基本属性:
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称
2.Bean标签范围配置
scope:指定对象的作用范围
取值及作用
取值范围 | 说明 |
---|---|
singleton | 默认值,单例 |
prototype | 多例 |
request | web项目中,spring创建一个Bean对象,将对象存储到request域中 |
session | web项目中,spring创建一个Bean对象,将对象存储到session域中 |
global session | web项目中,跨域环境中,将对象存储到global session域中,没有跨域环境,相当于session |
- singleton:
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心配置文件被加载时,实例化配置Bean实例
Bean的生命周期:
对象创建:当应用加载,创建容器时,对象就被创建
对象运行:只要容器存在,对象一直存在
对象销毁:当应用卸载,容器销毁时,对象就被销毁 - prototype:
Bean的实例化个数:多个(调用一次就是一个)
Bean的实例化时机:当调用getBean()方法才会实例化Bean
Bean的生命周期:
对象创建:当使用对象时,创建新的对象实例
对象运行:当前对象在使用时,就一直存在
对象销毁:当对象长时间不用时,被java的GC(垃圾回收机制)回收
Bean生命周期配置
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
public class SpringDemo02 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Persondao persondao = applicationContext.getBean("persondao",Persondao.class);
persondao.save();
}
}
<?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="userdao" class="com.wm.dao.impl.UserdaoImpl"></bean>
<bean id="persondao" class="com.wm.dao.impl.PersondaoImpl" init-method="init" destroy-method="destory"></bean>
</beans>
4.Bean实例化方式
1.使用无参构造器实例化
会根据默认的无参构造方法创建类的对象,如果Bean中没有默认无参构造方法,将创建失败
2.工厂静态方法实例化
创建静态方法工厂类
public class StaticFactory {
public static Userdao createUserdaoImpl(){
return new UserdaoImpl();
}
}
配置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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用工厂方式-->
<!-- 工厂静态方法返回Bean实例-->
<bean id="userdao" class="com.wm.dao.factory.StaticFactory" factory-method="createUserdaoImpl"></bean>
</beans>
测试
public class SpringDemo03 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Userdao userdao = applicationContext.getBean("userdao",Userdao.class);
userdao.te();
}
}
3.工厂实例方法实例化
工厂的非静态方法返回Bean实例
工厂的非静态方法
public class FactoryBean {
public Userdao createFactory(){
return new UserdaoImpl();
}
}
配置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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用工厂方式-->
<!-- 工厂静态方法返回Bean实例-->
<!-- <bean id="userdao" class="com.wm.dao.factory.StaticFactory" factory-method="createUserdaoImpl"></bean>-->
<!-- 工厂非静态方法返回Bean实例-->
<bean id="factory" class="com.wm.dao.factory.FactoryBean"></bean>
<bean id="userdao" factory-bean="factory" factory-method="createFactory"></bean>
</beans>
Bean的依赖注入(DI)
UserService—>UserDao
Bean的依赖注入的方式:
构造方法
public interface UserService {
void saveUser();
}
public class UserServiceImpl implements UserService {
private Userdao userdao;
public UserServiceImpl(){
System.out.println("userservice 无参构造器");
}
public UserServiceImpl(Userdao userdao){
this.userdao = userdao;
System.out.println("userservice 有参构造器");
}
public void saveUser() {
userdao.te();
}
}
<?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">
<!--配置userdaoimpl类-->
<!-- <bean id="userdao" class="com.wm.dao.impl.UserdaoImpl"></bean>-->
<!-- <bean id="persondao" class="com.wm.dao.impl.PersondaoImpl" init-method="init" destroy-method="destory"></bean>-->
<!-- 使用工厂方式-->
<!-- 工厂静态方法返回Bean实例-->
<!-- <bean id="userdao" class="com.wm.dao.factory.StaticFactory" factory-method="createUserdaoImpl"></bean>-->
<!-- 工厂非静态方法返回Bean实例-->
<!-- <bean id="factory" class="com.wm.dao.factory.FactoryBean"></bean>-->
<!-- <bean id="userdao" factory-bean="factory" factory-method="createFactory"></bean>-->
<!-- 通过构造器进行数据的注入-->
<bean id="userdao" class="com.wm.dao.impl.UserdaoImpl"></bean>
<bean id="userservice" class="com.wm.service.impl.UserServiceImpl">
<constructor-arg name="userdao" ref="userdao"></constructor-arg>
</bean>
</beans>
public class SpringDemo04 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = applicationContext.getBean("userservice",UserService.class);
userService.saveUser();
}
}
constructor-arg标签的属性
name:通过构造参数名称找到对应参数
type:通过类型找到对应参数
如果参数列表中类型一致时,建议不要通过类型设置进行注入,通过类型,会按照顺序进行依次注入
index:通过参数下标找到对应参数
value:参数值–只包含基本数据类型和String
ref:在Bean容器中查找id,将Bean容器中的值注入到当前参数
2.set方法:P命名注入
引入其他配置文件(分模块开发)
Spring的配置内容较多,体积较大,可以将spring根据业务、模块进行拆分,而在Spring的主配置文件中通过import标签进行加载
Spring注解开发
spring注解主要是替代“bean”的配置,使用注解代替xml配置内容,可以简化配置,提高开发效率
1.使用注解开发,需要在核心配置文件中,指定那个包下的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"
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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.wm"/>
</beans>
@Component("userdao") //使用在类上 用于实例化bean 相当于xml配置文件中的<bean>标签 value相当于标签中的id属性
public class UserdaoImpl implements Userdao {
public void save() {
System.out.println("save....");
}
}
public class SpringDemo01 {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Userdao userdao = applicationContext.getBean("userdao",Userdao.class);
userdao.save();
}
}
注解 | 说明 |
---|---|
@Component | 使用在类上用于实例化bean |
@Controller | 使用在web层类上用于实例化bean |
@Service | 使用在service层类上用于实例化bean |
@Repository | 使用在dao层类上用于实例化bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired,按照名称进行依赖注入 |
@Resource | 相当于@Autuwired+@Qualifier结合,按照名称进行依赖注入 |
@Scope | 作用在类上,标注bean作用范围 |
@PostConstruct | 作用在方法上,标注初始化方法 |
@PreDestory | 作用在方法上,标注销毁方法 |
数据库连接池的配置(druid数据库连接池的应用)
1.导入相应的jar坐标
druid的jar包
数据库驱动包
pom.xml坐标导入
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
Spring配置数据
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db1?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="10"/>
<property name="maxWait" value="3000"/>
</bean>
将jdbc的配置信息进行抽离,封装成配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db1?serverTimezone=UTC
jdbc.username=root
jdbc.password=root
jdbc.initialSize=5
jdbc.maxActive=10
jdbc.maxWait=3000
Spring容器加载properties文件
<context:property-placeholder location="xx.properties"/>
<property name="" value="${key}"/>
需要导入context标签约束
命名约束: xmlns:context="http://www.springframework.org/schema/context"
约束路径:http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
新注解的应用
开发中不适用xml配置文件,只使用相应的注解,进行开发操作
注解 | 说明 |
---|---|
@Configuration | 作用在类上,用于指定当前使用spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan | 作用在类上吗,用于指定Spring在初始化容器时,需要扫描哪些包,和<context:component-scan base-package=“com.wm”/>一样 |
@Bean | 做用在方法上,标注当前方法的返回值存储到spring容器中 |
@Import | 作用在类上,用于引入其他配置类 |
@PropertySource | 作用在类上,用于加载配置文件 |
@Value | 作用在字段(属性),用于注入基本类和Spring或者是Spring的EL表达式 依赖注入 |
脱离xml进行开发时
1.创建spring配置类
@Configuration
@ComponentScan(value = "com.wm")
public class SpringConfiguration {
}
2.测试类
public class Springdemo01 {
public static void main(String[] args) {
//使用纯注解开发 或者使用注解创建ApplicationContext
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService userService = context.getBean("userservice",UserService.class);
userService.Usersave();
}
}
@Bean注解,将当前方法的返回值,添加到容器中
Bean注解中name的定义类似于xml配置bean标签中的id属性
@Configuration
@ComponentScan(value = "com.wm")
public class SpringConfiguration {
@Bean(name = "datasource")
public DataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/db1?serverTimezone=UTC");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
public class SpringDemo02 {
public static void main(String[] args) throws SQLException {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
DataSource datasource = context.getBean("datasource", DataSource.class);
System.out.println(datasource);
Connection connection = datasource.getConnection();
System.out.println(connection);
}
}
@Value 作用在字段(属性),用于注入基本类和Spring或者是Spring的EL表达式 依赖注入
@Configuration
@ComponentScan(value = "com.wm")
public class SpringConfiguration {
@Value("com.mysql.cj.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/db1?serverTimezone=UTC")
private String url;
@Value("root")
private String username;
@Value("root")
private String password;
@Bean(name = "datasource")
public DataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
@PropertySource 作用在类上,用于加载配置文件
@Configuration
@ComponentScan(value = "com.wm")
@PropertySource("classpath:jdbc.properties")
public class SpringConfiguration {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name = "datasource")
public DataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
@Import
@Configuration
@ComponentScan(value = "com.wm")
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {
}
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name = "datasource")
public DataSource getDataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
Spring的AOP
1.AOP:面向切面编程,通过预编译方式和运行期动态代理实现程序的统一的维护的一种技术。
AOP是OOP的延续
2.AOP的作用和优势
作用:在程序运行期,在不改变源码的情况下,可以对方法进行增强
优势:减少重复性代码,提高开发效率,并且便于维护
3.AOP的底层实现
AOP的底层是通过Spring提供的动态代理技术实现的,在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时,进行增强功能的介入,再调用目标对象的方法,从而完成功能增强
4.AOP的动态代理技术
JDK代理:基于接口的动态代理技术
目标类的接口
public interface TargetInterface {
void save();
}
目标类
public class Target implements TargetInterface{
@Override
public void save() {
System.out.println("method...");
}
}
动态代理方式
public class Demo01 {
public static void main(String[] args) {
final Target target = new Target();
//JDK提供的动态代理类
TargetInterface targetInterface = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("记录日志");
Object invoke = method.invoke(target, args);
System.out.println("完毕");
return invoke;
}
});
targetInterface.save();
}
}
cglib代理
目标类
public class Target{
@Override
public void method() {
System.out.println("method...");
}
}
动态代理的应用
public class Demo02 {
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//使用动态生成代理对象 基于cglib
//1.创建增强器对象
Enhancer enhancer = new Enhancer();
//2.设置父类(目标类)
enhancer.setSuperclass(Target.class);
//3.设置回调
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("记录日志");
Object invoke = method.invoke(target, objects);
System.out.println("完毕");
return invoke;
}
});
Target proxy = (Target) enhancer.create();
proxy.method();
}
}
AOP相关术语
目标对象:代理的目标对象
代理:一个类被AOP织入增强,产生的结果代理类
连接点:指那些被拦截到的点(方法)
切入点:针对于哪些连接点进行拦截定义
增强/通知:指定连接点之后所有做的事情
切面:切入点和通知的结合人
基于xml的AOP开发
1.导包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- spring 应用的织入 -->
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
</dependencies>
2.创建目标接口和目标类(切点)
//省略了接口类
public class UserServiceImpl {
public void save(){
System.out.println("save...");
}
}
3.创建切面类(定义增强方法)
public class MyAspect {
public void bef(){
System.out.println("before...");
}
}
4.将目标类和切面类的创建权交给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
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.wm.service.UserServiceImpl"></bean>
<!-- 配这切面类-->
<bean id="myAspect" class="com.wm.service.MyAspect"></bean>
<!-- 配置切点表达式和增强的织入关系-->
<aop:config>
<!-- 引用myAspect的bean为切面类-->
<aop:aspect ref="myAspect">
<!-- 配置目标类的切入点-->
<aop:before method="bef" pointcut="execution(public void com.wm.service.UserServiceImpl.save())"></aop:before>
</aop:aspect>
</aop:config>
</beans>
1.切入点表达式
语法
execution(修饰符 返回值 包名.类名.方法名(参数))
修饰符:可以省略
返回值:可以用*表示,表示任意
包名、类名、方法名可以用*代替
execution(* *.*.*(参数))
参数列表可以使用…两个点,表示任意个数、任意类型参数
execution(* *.*.*(..))
public void com.wm.service.UserServiceImpl.save()
* *.*.*.*.*()
//只对UserServiceImpl下面所有的方法进行使用
* com.wm.service.UserServiceImpl.*(..)
//只对service包下面所有的类及方法进行应用
* com.wm.service.*.*(..)
//只对com下面所有的包进行应用
* com.*.*.*.*(..)//只针对于com下面两个包
* com..*.*(..)//在包下使用..两个点 表示当前包及其子包下
2.通知配置语法
<aop:before method="bef" pointcut="execution(* com..*.*(..))"></aop:before>
<aop:通知类型 method="通知方法名称" pointcut="切入点表达式"></aop:通知类型>
通知类型:前置通知(before),后置通知(after),异常通知(after-throwing),最终通知(after-returning),环绕通知
<?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.wm.service.UserServiceImpl"></bean>
<!-- 配这切面类-->
<bean id="myAspect" class="com.wm.service.MyAspect"></bean>
<!-- 配置切点表达式和增强的织入关系-->
<aop:config>
<!-- 引用myAspect的bean为切面类-->
<aop:aspect ref="myAspect">
<!-- 配置目标类的切入点-->
<aop:before method="bef" pointcut="execution(public void com.wm.service.UserServiceImpl.save())"></aop:before>
<aop:after method="after" pointcut="execution(* com..*.*.*(..))"></aop:after>
<aop:after-throwing method="runExpection" pointcut="execution(* com..*.*.*(..))"></aop:after-throwing>
<aop:after-returning method="runFinal" pointcut="execution(* com..*.*.*(..))"></aop:after-returning>
</aop:aspect>
</aop:config>
</beans>
环绕通知
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com..*.*.*(..))"/>
<aop:aspect ref="logger">
<aop:around method="aroundPrintcunt" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
public Object aroundPrintcunt(ProceedingJoinPoint pjp){
Object proceed = null;
try {
System.out.println("前置通知");
//获取方法急性所需的参数
Object[] args = pjp.getArgs();
//明确调用业务层方法(切入点方法)
proceed = pjp.proceed(args);
System.out.println("后置通知");
return proceed;
} catch (Throwable throwable) {
System.out.println("异常通知");
throwable.printStackTrace();
}finally {
System.out.println("最终通知");
return proceed;
}
}
基于注解AOP开发
<?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: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/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.wm.anno"/>
<!-- AOP的自动代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
切面类
@Component("myAspect")
@Aspect
public class MyAspect {
@Before("execution(* com..*.*(..))")
public void bef(){
System.out.println("before...");
}
@After("execution(* com..*.*(..))")
public void after(){
System.out.println("after...");
}
@AfterThrowing("execution(* com..*.*(..))")
public void runExpection(){
System.out.println("Exception...");
}
@AfterReturning("execution(* com..*.*(..))")
public void runFinal(){
System.out.println("final...");
}
@Around("execution(* com..*.*(..))")
public Object aroundPrintcunt(ProceedingJoinPoint pjp){
Object proceed = null;
try {
System.out.println("前置通知");
//获取方法急性所需的参数
Object[] args = pjp.getArgs();
//明确调用业务层方法(切入点方法)
proceed = pjp.proceed(args);
System.out.println("后置通知");
return proceed;
} catch (Throwable throwable) {
System.out.println("异常通知");
throwable.printStackTrace();
}finally {
System.out.println("最终通知");
return proceed;
}
}
}
目标类
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void method() {
System.out.println("method...");
}
}
@Pointcut()//定义切入点表达式
1.定义一个方法
public void pt1(){}
2.在当前方法上使用Pointcut注解
@Pointcut("execution(* com..*.*(..))")
public void pt1(){}
3.使用切入点
@Before("pt1()")
public void bef(){
System.out.println("before...");
}
@After("MyAspect.pt1()")
public void after(){
System.out.println("after...");
}