标签:jdk动态代理 参数 prope itext 层次结构 password 签名 roo 名称查找
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
优点:
总结:Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架
Maven仓库:
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
Spring框架是一个分层架构,由7个定义好的模块组成,Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式
组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现,每个模块的功能如下:
Spring core:核心容器提供Spring框架的基本功能,核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开
Spring context:Spring context是一个配置文件,向Spring框架提供上下文信息,Spring context包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能
Spring DAO:JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息,异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构
Spring AOP:通过配置管理特性,Spring AOP模块直接将面向切面的编程功能,集成到了Spring框架中,所以,可以很容易地使Spring框架管理任何支持AOP的对象。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务,通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中
Spring ORM:Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、Hibernate 和iBatis SQL Map。所有这些都遵从Spring的通用事务和DAO异常层次结构
Spring WEB:Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文,所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作
Spring MVC:MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提, 需要完全掌握Spring及SpringMVC,承上启下的作用
弊端:发展了太久之后,违背了原来的理念,配置十分繁琐,人称:”配置地狱”
UserDao接口
UserDaoImpl实现类
UserService业务接口
UserServiceImpl实现类
注:之前的业务中,用户的需求可能会影响原来的代码,需要根据用户的需求去修改原代码,如果程序代码量十分大,修改一次的成本代价十分昂贵
解决:使用一个set接口实现
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
总结:这种思想,从本质上解决了问题,程序猿不用再去管理对象的创建了,系统的耦合性大大降低,可以更加专注的在业务的实现上,这是IOC思想的原型
控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法
没有loC的程序中, 我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)
编写实体类(重点set方法)
package com.believe.pojo;
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 + ‘\‘‘ +
‘}‘;
}
}
编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--以前创建对象的方式:Hello hello = new Hello();-->
<!--使用spring:id(变量名)、class(要创建对象的类)、property(属性)、value(设置值)-->
<bean id="hello" class="com.believe.pojo.Hello" >
<!--ref:引用Spring容器中创建好的对象
value:具体的值,基本数据类型-->
<property name="str" value="HelloSpring!" />
</bean>
</beans>
测试
public static void main(String[] args) {
//获取ApplicationContext,拿到Spring容器,参数可以是多个
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//在容器中获取到对象(bean),参数为对象的id,也就是通过id获取对象
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello);
}
Hello对象是谁创建的?
hello对象是由Spring创建的
Hello对象的属性是怎么设置的?
hello对象的属性是由Spring容器设置的
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象的是由Spring来创建的
反转:程序本身不创建对象,变成被动的接收对象
依赖注入:就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收
总结:IOC思想就是对象由Spring来创建,管理,装配!不用在程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改
默认使用无参构造创建,如果实体类中没有无参构造方法,则会报错
No default constructor found;
使用下标赋值
<bean id="hello" class="com.believe.pojo.Hello">
<constructor-arg index="0" value="hello"/>
</bean>
数据类型赋值
<bean id="hello" class="com.believe.pojo.Hello">
<constructor-arg type="java.lang.String" value="hello"/>
</bean>
属性名称赋值
<bean id="hello" class="com.believe.pojo.Hello">
<constructor-arg name="str" value="hello"/>
</bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了
<!--取别名,可以通过别名来获取对象,一次只能起一个别名-->
<alias name="heelo" alias="helloNew"/>
<!--
id:bean的唯一标识符,也就是对象名
class:bean对象对应的全限定名=包名+类名
name:也是别名,可以取多个别名,可用空格或者,或者;分割
-->
<bean id="hello" class="com.believe.pojo.Hello" name="hello01 hello02,hello03;hello04">
<constructor-arg name="str" value="hello"/>
</bean>
作用:一般用于团队开发使用,可以将多个配置文件,导入合并为一个
<!--导入其他配置文件(用于团队协作开发)-->
<import resource="beans01.xml"/>
<import resource="beans02.xml"/>
<import resource="beans03.xml"/>
使用无参构造或者有参构造注入
依赖注入:set注入
环境搭建:
复杂类型
package com.believe.pojo;
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 + ‘\‘‘ +
‘}‘;
}
}
真实测试对象
package com.believe.pojo;
import java.util.*;
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 girlfriend;
private Properties info;
}
applicationContext.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.believe.pojo.Address" >
<property name="address" value="郑州" />
</bean>
<bean id="student" class="com.believe.pojo.Student" >
<!--普通注入,直接value赋值即可-->
<property name="name" value="坤坤" />
<!--引用注入-->
<property name="address" ref="address" />
<!--数组注入-->
<property name="books" >
<array>
<value>红楼梦</value>
<value>水浒传</value>
<value>西游记</value>
</array>
</property>
<!--list注入-->
<property name="hobbies" >
<list>
<value>唱</value>
<value>跳</value>
<value>rap</value>
<value>篮球</value>
</list>
</property>
<!--map注入-->
<property name="card" >
<map>
<entry key="学生卡" value="20200520" />
<entry key="身份证" value="66666666" />
</map>
</property>
<!--set注入-->
<property name="games" >
<set>
<value>cf</value>
<value>dnf</value>
<value>lol</value>
</set>
</property>
<!--null注入-->
<property name="girlfriend" >
<null/>
</property>
<!--properties注入-->
<property name="info" >
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
测试
package com.believe.test;
import com.believe.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
/*Student{
name=‘坤坤‘,
address=Address{address=‘郑州‘},
books=[红楼梦, 水浒传, 西游记],
hobbies=[唱, 跳, rap, 篮球],
card={学生卡=20200520, 身份证=66666666},
games=[cf, dnf, lol],
girlfriend=‘null‘,
info={password=123456, username=root}}
*/
}
}
总结:用的比较多的就是普通注入和引用注入
可以使用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="user1" class="com.believe.pojo.User" p:name="张三" p:age="18"/>
<!--c命名空间注入,通过构造器注入值:construct-->
<bean id="user2" class="com.believe.pojo.User" c:name="张三" c:age="18"/>
</beans>
测试:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = context.getBean("user1", User.class);
System.out.println(user\.toString());
User user2 = context.getBean("user2", User.class);
System.out.println(user2.toString());
}
总结:p命名空间和c命名空间可以直接使用,需要导入约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
singleton 单例模式(Spring默认机制):每次从容器get的都是同一个对象
<bean id="user1" class="com.believe.pojo.User" p:name="张三" p:age="18" scope="singleton" />
prototype原型模式:每次从容器中get的时候,都会产生一个新的对象
<bean id="user2" class="com.believe.pojo.User" c:name="张三" c:age="18" scope="prototype" />
其余的request、session、application、websocket这些都只能在web开发中使用到
package com.believe.pojo;
public class People {
private Cat cat;
private Dog dog;
private String 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 String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name=‘" + name + ‘\‘‘ +
‘}‘;
}
}
<bean id="cat" class="com.believe.pojo.Cat" />
<bean id="dog" class="com.believe.pojo.Dog" />
<bean id="people" class="com.believe.pojo.People" >
<property name="name" value="哈哈" />
<property name="cat" ref="cat" />
<property name="dog" ref="dog" />
</bean>
<bean id="cat" class="com.believe.pojo.Cat" />
<bean id="dog" class="com.believe.pojo.Dog" />
<!--byName:会自动在容器上下文中查找bean的set方法后面值对应的id-->
<bean id="people" class="com.believe.pojo.People" autowire="byName" >
<property name="name" value="哈哈" />
</bean>
<bean class="com.believe.pojo.Cat" />
<bean class="com.believe.pojo.Dog" />
<!--byType:会自动在容器上下文中查找和自己对象属性类型相同的bean-->
<bean id="people" class="com.believe.pojo.People" autowire="byType" >
<property name="name" value="哈哈" />
</bean>
注:
除了byName和byType自动装配方式,Spring还支持注解自动装配
导入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:annotation-config/>
在实体类添加注解
@Autowired
private Cat cat;
@Autowired
private Dog dog;
扩展:
总结:
@Resource,相当于@Autowired和@Qualifier的组合体
@Resource
private Cat cat;
@Resource
private Dog dog;
@Autowired和@Resouce的区别:
它们的作用相同都是用注解方式注入对象,但执行顺序不同,@Autowired先byType,@Resource先byName
为什么要学习代理模式,因为AOP的底层机制就是动态代理
代理模式的定义:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用
学习aop之前 , 我们要先了解一下代理模式
代理模式:
静态代理角色分析
代码实现
Rent.java即抽象角色
package com.believe.proxy;
//抽象角色:出租
public interface Rent {
public void rentHouse();
}
Host.java即真实角色
package com.believe.proxy;
//真实角色:房东
public class Host implements Rent {
public void rentHouse() {
System.out.println("房东出租房子");
}
}
Proxy.java即代理角色
package com.believe.proxy;
//代理角色:中介
public class Proxy implements Rent {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rentHouse() {
helpHost();
host.rentHouse();
visitHouse();
agencyFee();
}
//托管中介
public void helpHost() {
System.out.println("中介帮助房东");
}
//客户看房
public void visitHouse() {
System.out.println("带客户看房子");
}
//付中介费
public void agencyFee() {
System.out.println("中介收中介费");
}
}
Client.java即客户
package com.believe.proxy;
//客户,一般客户去找代理
public class Client {
public static void main(String[] args) {
//房东出租房子
Host host = new Host();
//中介帮助房东
Proxy proxy = new Proxy(host);
//找中介租房子
proxy.rentHouse();
}
}
流程分析:在这个过程中,客户直接接触的就是中介,就如同现实生活中的样子,客户看不到房东,但是客户通过代理依旧租到了房东的房子,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情
静态代理优点:
静态代理缺点:
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理
练习步骤:
创建一个抽象角色
package com.believe.dynamicProxy;
//抽象角色:增删改查业务
public interface UserService {
public void add();
public void del();
public void set();
public void get();
}
真实角色完成增删改查操作
package com.believe.dynamicProxy;
//真实角色:完成增删改查操作的实现类
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加用户");
}
public void del() {
System.out.println("删除用户");
}
public void set() {
System.out.println("修改用户");
}
public void get() {
System.out.println("查询用户");
}
}
需求来了,需要增加一个日志功能,怎么实现?
代理角色来处理日志
package com.believe.dynamicProxy;
//代理角色:增加日志的实现
public class UserServiceProxy implements UserService {
private UserServiceImpl userServiceImpl;
public UserServiceProxy() {
}
public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
public void add() {
log("add");
userServiceImpl.add();
}
public void del() {
log("del");
userServiceImpl.del();
}
public void set() {
log("set");
userServiceImpl.set();
}
public void get() {
log("get");
userServiceImpl.get();
}
private void log(String msg) {
System.out.println("执行了"+msg+"方法");
}
}
测试访问类
package com.believe.dynamicProxy;
//客户:通过代理角色实现日志添加
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userServiceImpl = new UserServiceImpl();
//代理角色
UserServiceProxy userServiceProxy = new UserServiceProxy();
userServiceProxy.setUserServiceImpl(userServiceImpl);
userServiceProxy.add();
userServiceProxy.del();
userServiceProxy.set();
userServiceProxy.get();
}
}
理解思想:在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想
**JDK的动态代理需要了解两个类:InvocationHandler和Proxy **
InvocationHandler:调用处理程序
InvocationHandler是由代理实例调用处理程序实现的接口 每个代理实例都有一个关联的调用处理程序,当在代理实例上调用方法时,调用的方法进行编码并分派其调用处理程序的invoke方法
//在代理实例上处理方法调用,并返回结果
//当在与它关联的代理实例上调用方法时,该方法将在调用处理程序上调用此方法
invoke(Object proxy, Method method, Object[] args)
//proxy,调用该方法的代理实例
//method,此方法对应调用代理实例上的接口的实例方法,对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口
//args,包含在方法上通过代理实例调用的实参的值、对象的数组或null,如果接口方法不需要参数,原始类型的实参是包裹在适当的原始包装类的实例,如java.lang.Integer或java.lang.Boolean
Proxy : 代理
Proxy提供了创建动态代理类实例的静态方法,也是所有动态代理类的父类的方法创建
每个代理实例有一个关联的调用处理程序对象,它实现了接口InvocationHandler
//创建由指定的类加载器定义的代理类的指定调用处理程序的代理实例,并实现指定的接口
newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)
//loader,类装载器来定义代理类
//interfaces,为代理类实现的接口列表
//h,调用处理程序进行方法调用
代码实现
Rent.java即抽象角色
package com.believe.dynamicProxy;
//抽象角色:出租
public interface Rent {
public void rentHouse();
}
Host.java即真实角色
package com.believe.dynamicProxy;
//真实角色:房东
public class Host implements Rent {
public void rentHouse() {
System.out.println("房东出租房子");
}
}
ProxyInvocationHandler.java即代理角色
package com.believe.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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,此方法对应调用代理实例上的接口的实例方法
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
helpHost();
//动态代理本质使用反射机制实现
Object result = method.invoke(rent, args);
visitHouse();
agencyFee();
return result;
}
//托管中介
public void helpHost() {
System.out.println("中介帮助房东");
}
//客户看房
public void visitHouse() {
System.out.println("带客户看房子");
}
//付中介费
public void agencyFee() {
System.out.println("中介收中介费");
}
}
Client.java即客户
package com.believe.dynamicProxy;
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用代理程序处理要调用的接口对象
pih.setRent(host);//设置要代理的对象
//动态生成代理类
Rent proxy = (Rent) pih.getProxy();
proxy.rentHouse();
}
}
使用动态代理实现代理UserService添加日志功能
package com.believe.proxyInvocationHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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);
}
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+"方法");
}
}
测试
package com.believe.proxyInvocationHandler;
import com.believe.staticProxy.UserService;
import com.believe.staticProxy.UserServiceImpl;
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userServiceImpl = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置要代理的对象
pih.setTarget(userServiceImpl);
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.add();
proxy.del();
proxy.set();
proxy.get();
}
}
静态代理有的它都有,静态代理没有的,它也有
面向切面编程(Aspect Oriented Programming,缩写为:AOP),通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
提供声明式事务,允许用户自定义切面
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
通知类型 | 连接点 |
---|---|
Before前置通知 | 方法执行开始前执行 |
After后置通知 | 方法执行结束后执行 |
AfterReturning返回通知 | 方法正常执行之后执行的代码 |
AfterThrowing异常通知 | 方法抛出异常时 |
Around环绕通知 | 方法执行开始前和结束后执行 |
即AOP在不改变原有代码的情况下,去增加新的功能
使用AOP织入,需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
创建切面:BeforeLog.java
package com.believe.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
//method,要执行的目标对象的方法
//objects,参数
//o,目标对象
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行了");
}
}
applicatContext.xml
<!--方式一:使用原生的Spring API接口-->
<!--配置AOP:需要导入AOP的约束-->
<aop:config>
<!--切入点:pointcut-->
<!--expression:表达式execution()-->
<aop:pointcut id="pointcut" expression="execution(* com.believe.service.UserServiceImpl.*(..))" />
<!--执行环绕增加-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut" />
<aop:advisor advice-ref="afterReturningLog" pointcut-ref="pointcut" />
</aop:config>
测试
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
userServiceImpl.del();
userServiceImpl.set();
userServiceImpl.get();
}
}
自定义切面类,DiyPointCut.java
package com.believe.diy;
public class DiyPointCut {
public void before() {
System.out.println("===方法前===");
}
public void after() {
System.out.println("===方法后===");
}
}
applicatContext.xml
<!--方式二:自定义切面-->
<bean id="diy" class="com.believe.diy.DiyPointCut" />
<aop:config>
<!--自定义切面,ref要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.believe.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:after method="after" pointcut-ref="pointcut" />
<aop:before method="before" pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
测试
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
userServiceImpl.del();
userServiceImpl.set();
userServiceImpl.get();
}
}
自定义切面类,AnnotationPointCut.java
package com.believe.anno;
//方式三:使用注解方式实现AOP
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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 AnnotationPointCut {
@Before("execution(* com.believe.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("==方法前==");
}
@After("execution(* com.believe.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("==方法后==");
}
//在环绕增强中,可以给定一个参数,代表要处理切入的点
@Around("execution(* com.believe.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("环绕前");
//执行方法
Object proceed = pj.proceed();
System.out.println("环绕后");
/*获得签名
Signature signature = pj.getSignature();
System.out.println(signature);
System.out.println(proceed);*/
}
}
applicatContext.xml
<!--方式三:使用注解实现-->
<bean id="annotationPointCut" class="com.believe.anno.AnnotationPointCut" />
<!--开启注解支持.,jdk(默认proxy-target-class="false"),cjlib(proxy-target-class="true")-->
<aop:aspectj-autoproxy />
测试
package com.believe.test;
import com.believe.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口:注意点
UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
userServiceImpl.add();
}
}
标签:jdk动态代理 参数 prope itext 层次结构 password 签名 roo 名称查找
原文地址:https://www.cnblogs.com/thetree/p/Spring.html