文章目录
1.Spring认知
1.1 简介
//下载链接
https://repo.spring.io/ui/native/libs-release-local/org/springframework/spring/
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.8</version>
</dependency>
1.2 优点
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级的、非入侵式的框架
- 控制反转(IOC)、面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
==总结:Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)编程的框架
1.3 组成
1.4 拓展
在Spring的官网有这个介绍:现代化的Java开发,就是基于Spring的开发
- Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速的开发单个微服务
- 约定大于配置
- Spring Cloud
- SpringCloud是基于SpringBoot实现的
弊端:配置地狱
2.IOC理论推导
在业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码。如果程序代码两十分大,修改一次的成本代价十分昂贵
我们使用一个Set接口实现
private UserDao userDao;
// 利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//如何调用
UserService userService = new UserServiceImpl();
((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
userService.getUser();
-
之前,程序是主动创建对象,控制权在程序员手上
-
使用了set注入后,程序不在具有主动性,而是变成了被动的接受对象
-
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注的在业务的实现上。这是IOC的原型
2.1 IOC本质
控制反转IOC(Inversion of control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)
3.HelloSpring
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">
<!-- 这两行就相当于获取了两个dao的实现接口类,下面ref传其中一个-->
<bean id="mysqlImpl" class="com.lz.dao.UserDaoMysqlImpl"/>
<bean id="Impl" class="com.lz.dao.UserDaoImpl"/>
<!-- 这个相当于获取了service的实现接口类,里面有个set方法,动态注入-->
<bean id="UserServiceImpl" class="com.lz.service.UserServiceImpl">
<!-- ref:引用Spring容器中创建好的对象-->
<!-- 这个就相当于获取了那个userDao变量,给他动态实例对象通过ref确定-->
<property name="userDao" ref="mysqlImpl"/>
</bean>
</beans>
测试类
public class Test {
public static void main(String[] args) {
// UserService userService = new UserServiceImpl();
//
// ((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
//
// userService.getUser();
//拿到Spring容器(上下文),Spring帮助我们完成了实例对象的操作
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");//xml中bean的id
userServiceImpl.getUser();
}
}
service层的实现接口类
public class UserServiceImpl implements UserService{
private UserDao userDao;
// 利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
这个时候,我们不用再去修改程序了,要实现不同的操作和结果显示,只需要在xml配置文件中进行修改,所谓的IOC,用一句话来说,就是:对象由Spring来创建,管理,装配
- 所有的类都需要装配到bean里面
- 所有的bean都需要通过容器去取
- 容器里的bean拿出来就是一个对象
4.IOC创建对象的方式
-
默认使用无参构造创建对象,默认
-
假设我们要使用有参构造创建对象
-
下标赋值
<!-- 第一种,下标赋值--> <bean id="user" class="com.lz.pojo.user"> <constructor-arg index="0" value="====="/> </bean>
-
类型
<!-- 第二种,通过类型创建,不建议使用--> <bean id="user" class="com.lz.pojo.user"> <constructor-arg type="java.lang.String" value="======"/> </bean>
-
参数名(主要)
<!-- 第三种,直接通过参数名来设置--> <bean id="user" class="com.lz.pojo.user"> <constructor-arg name="name" value="======"/> </bean>
-
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了
5.Spring配置
5.1 别名
<!-- 别名,如果添加了别名,我们也可以使用别名获取到这个对象,这个name是bean的 id-->
<alias name="UserServiceImpl" alias="service"/>
5.2 Bean的配置
<!--
id:bean的唯一标识符,也就是相当于我们学的对象名
class:bean对象所对应的全限定名:包名 + 类型
name:也是别名,而且name可以同时取多个别名
-->
<bean id="" class="" name="">
<property name="" value=""/>
</bean>
5.3 import
这个import,一般用于团队开发使用,它可以将多个配置文件,导入合并为一个
假如,现在项目中有多个人开发,这几个人开发不同的类,且都需要注册不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的(能合并同类项)
<!-- applicationContext.xml中 -->
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>
<import resource="bean3.xml"/>
使用时,直接使用总的配置就可以了
6.依赖注入(DI)
6.1 构造器注入
第4大点有例子
6.2 Set方式注入【重点】
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入
【环境搭建】
-
复杂类型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Address{" + "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 wifi; private Properties info; //一堆get、set……………… @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address=" + address.toString() + ", books=" + Arrays.toString(books) + ", hobbies=" + hobbies + ", card=" + card + ", games=" + games + ", wifi='" + wifi + '\'' + ", 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.lz.pojo.Address"> <property name="address" value="北京"/> </bean> <bean id="student" class="com.lz.pojo.Student"> <!-- 第一种,普通值注入,value--> <property name="name" value="haha"/> <!-- 第二种,Bean注入,ref--> <property name="address" ref="address"/> <!-- 数组--> <property name="books"> <array> <value>红楼梦</value> <value>西游记</value> <value>水浒传</value> <value>三国演义</value> </array> </property> <!-- List--> <property name="hobbies"> <list> <value>听歌</value> <value>敲代码</value> <value>看电影</value> </list> </property> <!-- Map--> <property name="card"> <map> <entry key="身份证" value="123456789"/> <entry key="银行卡" value="112233445566"/> </map> </property> <!-- Set--> <property name="games"> <set> <value>LOL</value> <value>COC</value> <value>BOB</value> </set> </property> <!-- null--> <property name="wifi"> <null/> </property> <!-- Properties--> <property name="info"> <props> <prop key="driver">mysql</prop> <prop key="url">本地</prop> <prop key="username">小红</prop> <prop key="password">123456</prop> </props> </property> </bean> </beans>
-
测试类
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student); /* Student{ name='haha', address=Address{address='北京'}, books=[红楼梦, 西游记, 水浒传, 三国演义], hobbies=[听歌, 敲代码, 看电影], card={身份证=123456789, 银行卡=112233445566}, games=[LOL, COC, BOB], wifi='null', info={password=123456, url=本地, driver=mysql, username=小红} } */ } }
6.3 拓展方式注入
我们可以使用p命名空间和c命名空间进行注入
官方解释:
<?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">
<!-- p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.lz.pojo.User" p:name="haha" p:age="18"/>
<!-- c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="com.lz.pojo.User" c:name="liele" c:age="22"/>
</beans>
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
//User.class声明类型后就不用再强转了
User user = context.getBean("user", User.class);
System.out.println(user);
注意点:p命名和c命名空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
6.4 bean的作用域(默认单例)
- 单例模式(Spring默认机制)
<bean id="user2" class="com.lz.pojo.User" c:name="liele" c:age="22" scope="singleton"/>
- 原型模式:每次从容器中get的时候,都会产生一个新对象
<bean id="user" class="com.lz.pojo.User" scope="prototype"/>
- 其余的request、session、application这些只能在web开发中使用到
7.Bean的自动装配
- 自动装配是Spring满足bean依赖一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种自动装配的方式
- 在xml中显示的配置
- 在java中显示配置
- 隐式的自动装配bean【重要】
7.1 测试
环境搭建:一人两宠物
7.2 ByName自动装配和ByType自动装配
<bean id="cat" class="com.lz.pojo.Cat" />
<bean id="dog" class="com.lz.pojo.Dog" />
<!--
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean的id
byType:会自动在容器上下文中查找,和自己对象属性类型(class)相同的bean
-->
<bean id="people" class="com.lz.pojo.People" autowire="byName">
<property name="name" value="mua" />
</bean>
<bean id="people" class="com.lz.pojo.People" autowire="byType">
<property name="name" value="mua" />
</bean>
小结:
- byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
- bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
7.3 使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持注解了
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
要使用注解须知:
-
导入约束:context约束
-
配置注解的支持: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(优先按类型找,找到多个就按名字找,两者都找不到就报错)
直接在属性上使用即可!也可以在set方法上使用
当出现这种情况时:
<bean id = "cat1" class = "com.lz.test.Cat">
<bean id = "cat2" class = "com.la.test.Cat">
private Cat cat1;
private Cat cat2;
private Cat cat;
类型重复时,使用@Qualifier(value = “cat1”)匹配id来帮助@Autowired来区分
- 总结:@Autowired先bytype,多个再按byname,对不上就加上@Qualifier(value = “xxx”)来帮助区分
科普:
@Nullable 字段标记了这个注解,说明这个字段可以为null
public @interface Autowired{
boolean required() default true;
}
@Autowired(required = false) 如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
@Resource注解
( @Resource默认按照名称进行装配,找不到名称找类型【jdk原生注解,新版本弃用了】找唯一的bean==) (类似@Autowired和@Qualifier(value = “xxx”)的结合)
@Resource(name = "cat")
private Cat cat;
小结:
@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过byType的方式实现,而且必须要求这个对象存在【常用】
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType。如果都找不到的情况下,就报错【常用】
- 执行顺序不同:@Autowired通过byType的方式实现。@Resource默认通过byname的方式实现
8.使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入了==
使用注解需要导入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"
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:component-scan base-package="com.lz.pojo"/>
<!-- 开启注解的支持 -->
<context:annotation-config/>
</beans>
-
bean
-
属性如何注入
//等价于<bean id="user" class="com.lz.poji.User"/> //Component 组件 @Component public class User { // //相当于<property name="name" value="haha"/> // @Value("haha") public String name; //相当于<property name="name" value="haha"/> @Value("haha") public void setName(String name) { this.name = name; } }
-
衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao【@Repository】
- service【@Service】
- controller【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
-
自动装配
- @Autowired : 自动装配类型,名字; 如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value = "xxx") - @Nullable 字段标记了这个注解,说明这个字段可以为null - @Resource : 自动装配名字,类型
-
作用域
@Scope("singleton")………………
-
小结
-
xml与注解;
- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己类使用不了,维护相对复杂
-
xml与注解最佳实践:
-
xml用来管理bean
-
注解只负责完成属性的注入
-
我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!-- 指定要扫描的包,这个包下的注解就会生效--> <context:component-scan base-package="com.lz"/> <!-- 开启注解的支持 --> <context:annotation-config/>
-
-
9.使用java的方式配置Spring
我们现在要完全不适用Spring的xml配置了,全权交给Java来做
JavaConfig是Spring的一个子项目,在Spring 4之后,它成为了一个核心功能
实体类
//这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("haha")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
配置类
/*
这个也会被Spring容器托管,注册到容器中,因为他本来就是一个@Component
@Configuration代表这是一个配置类,就和我们之前的beans.xml一样
*/
@Configuration
//@ComponentScan("com.lz.pojo")
//@Import(MyConfig.class)
public class MyConfig {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User getUser(){
return new User();
}
}
测试类
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User getUser = (User) context.getBean("getUser");
System.out.println(getUser.getName());
}
}
-
使用Component注解+ComponentScan注解的效果与Configeration+Bean注解类似
-
最好不要混用,Component注解+ComponentScan扫描会自动生成一个默认id为user( User类的默认bean-id 为user )的对象
这种纯java的配置方式,在SpringBoot中随处可见
10.代理模式
为什么要学习代理模式?因为这就是SpringAOP的底层!
代理模式的分类:
- 静态代理
- 动态代理
10.1 静态代理
角色分析:
- 抽象角色:一般会使用决口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
-
接口
public interface Rent { public void rent(); }
-
真实角色
public class Host implements Rent{ @Override public void rent() { System.out.println("房东要出租房子"); } }
-
代理角色
public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { seeHouse(); host.rent(); hetong(); fare(); } // 看房 public void seeHouse(){ System.out.println("中介带你看房"); } // 签合同 public void hetong(){ System.out.println("签合同"); } // 收中介费 public void fare(){ System.out.println("收中介费"); } }
-
客户端访问代理角色
public class Client { public static void main(String[] args) { // 房东要租房子 Host host = new Host(); // 代理,中介帮房东租房子,但是,代理一般会有一些附属的操作 Proxy proxy = new Proxy(host); // 不用面对房东,直接找中介租房即可 proxy.rent(); } }
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共业务就交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
缺点:
- 一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低
10.2 加深理解
聊聊AOP
10.3 动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口 — JDK动态代理【我们在这里使用】
- 基于类:cglib
- java字节码实现:javassist
需要了解两个类:Proxy,InvocationHandler:调用处理程序
例子:
封装好的动态代理类
//等会会用着这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
/**
* 生成得到代理类
* Proxy.newProxyInstance三个参数的意思
* this.getClass().getClassLoader()固定的;为了加载的类在哪个位置
* rent.getClass().getInterfaces()被代理类的接口;表示代理的接口是哪个
* this是InvocationHandler,即是类本身
* 这是一个几乎固定写法的方法
*
* @return
*/
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 {
log(method.getName());
// 动态代理的本质,就是使用反射机制实现
Object result = method.invoke(target, args);
return result;
}
public void log(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.delete();
proxy.add();
}
}
动态代理的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共业务就交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可
11.AOP
AOP在Spring中的作用
提供声明式事务:允许用户自定义切面
=================================================================================
11.1 使用Spring实现AOP==
【重点】使用AOP织入,需要导入一个依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
<scope>runtime</scope>
</dependency>
以下方式共有的:
UserService接口类
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
UserServiceImpl实现接口类
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 select() {
System.out.println("查询了一个用户");
}
}
测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 动态代理代理的是接口:注意点
UserService userService = (UserService) context.getBean("userService");
userService.add();
//......
}
}
配置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
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-->
<bean id="userService" class="com.lz.service.UserServiceImpl"/>
</beans>
方式一:使用Spring的API接口【主要SpringAPI接口实现】
配置xml(插入到共有xml中)
<!-- 方式一:使用原生Spring API接口-->
<bean id="log" class="com.lz.log.Log"/>
<!-- 配置aop:需要导入aop的约束-->
<aop:config>
<!-- 切入点:expression:表达式,execution(要执行的位置! * * * * *)-->
<aop:pointcut id="pointcut" expression="execution(* com.lz.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
</aop:config>
Log类
public class Log implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//args:参数
//target:目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
方式二:自定义来实现AOP【主要是切面定义】
配置xml(插入到共有xml中)
<!-- 方式二:自定义类-->
<bean id="diy" class="com.lz.diy.DiyPointCut"/>
<aop:config>
<!-- 自定义切面,ref要引用的类-->
<aop:aspect ref="diy">
<!-- 切入点-->
<aop:pointcut id="point" expression="execution(* com.lz.service.UserServiceImpl.*(..))"/>
<!-- 通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
DiyPointCut类
public class DiyPointCut {
public void before(){
System.out.println("======方法执行前=========");
}
public void after(){
System.out.println("======方法执行后=========");
}
}
方式三:使用注解实现
配置xml(插入到共有xml中)
<!-- 方式三-->
<bean id="annotationPointCut" class="com.lz.diy.AnnotationPointCut" />
<!-- 开启注解支持 JDK(默认 proxy-target-class="false") cglib(proxy-target-class="true")-->
<aop:aspectj-autoproxy />
AmmotationPointCut类
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.lz.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("=====方法执行前========");
}
@After("execution(* com.lz.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("=====方法执行后========");
}
// 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.lz.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
// 执行方法
Object proceed = jp.proceed();
System.out.println("环绕后");
}
}