1.依赖注入扩展
.1.1构造注入
Spring通过setter访问器实现对属性的赋值行为被称为“设值注入”。Spring通过构造方法赋值的能力,称为构造注入。
示例:
1.编写一个简单的类,添加有参和无参构造
/**
* Desc:测试实体类
* createBy:
* Date: 2019/7/6 0006 0:02
*/
public class EntityUser {
private String name;
private String age;
public EntityUser() {
}
public EntityUser(String name, String age) {
this.name = name;
this.age = age;
}
public void print(){
System.out.println("姓名:"+"年龄是:"+age);
}
使用设值注入时,Spring通过JavaBean的无参构造方法实例化对象。当编写带参构造方法后,Java虚拟机不在提供默认的无参构造。为了保证使用的灵活性,最好添加一个无参构造。
2.在Spring的配置文件中将name属性和age属性以构造注入的方式赋值给EntityUser对象。代码如下:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<!--通过定义的有参构造为对象的属性name和age赋值-->
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="18"/>
</bean>
经验:
1、一个<consturcotr-arg>元素表示构造方法的一个参数,且使用时不区分顺序,当构造方法的参数出现混淆、无法区分时,可以通过<consturcotr-arg>元素的index属性指定该参数的位置索引,索引从0开始。<consturcotr-arg>还提供了type属性用来指定参数的类型,避免字符串和基本数据类型的混淆。
2、构造注入的时效性好,在对象实例化时就得到所依赖的对象,便于在对象的初始化方法中使用依赖对象;但受于方法重载的形式,使用灵活性不足。设置注入使用灵活,但时效性不好。
3、Spring还提供了多种注入方式。
1.2 命名空间注入
p 命名空间的特点是使用属性而不是子元素的形式来配置Bean的属性,从而简化Bean的配置。
使用p命名空间进行属性的注入需要添加P命名空间的声明。
直接量(基本数据类型、字符串)属性,使用方式如下:
语法 p:属性名 =“属性值”。
引用Bean的属性,使用方式如下:
语法 p:属性名-ref=“Bean的id”.
代码如下:
<?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"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd">
<!--通过p命名空间注入属性值-->
<bean id="entityUser" class="cn.kgc.Entity.EntityUser"
p:name="张三" p:age="18" p:hobby-ref="hobby">
</bean>
1. 3.注入不同数据类型
Spring提供了不同的标签来实现各种不同类型参数的注入,这些标签对于设值注入和构造注入都适用。
1.注入直接量(基本数据类型、字符串)
对于 基本数据类型及其包装类、字符串,除了可以使用value属性,还可以通过<value>子元素进行注入,
<!--通过value属性注入-->
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="name">
<value>张三</value>
</property>
<property name="age">
<value>18</value>
</property>
</bean>
如果属性中包含了xml中的特殊字符(&、<、>、"、’),则注入时需要进行处理。通常可以采用两种办法:
一、使用<![CDATA[]]>标记或把特殊字符替换为实体引用。
二、使用实体引用放肆
XML中的五个实体引用:
符号 | 实体引用 |
---|---|
< | < ; |
> | > ; |
& | & amp; |
, | & apos; |
" | " ; |
2、引用其他Bean组件
Spring中定义的Bean可以互相引用,从而建立以来关系,除了使用ref属性,还可以通过<ref>子元素实现。示例如下:
<bean id="hobby" class="cn.kgc.Hobby"/>
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="name">
<ref bean="hobby"/>
</property>
</bean>
<ref>标签中的bean属性用来指定要引用的Bean的id。除了bean属性,在介绍一个local属性的用法。代码如下
<bean id="hobby" class="cn.kgc.Hobby"/>
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="name">
<ref local="hobby"/>
</property>
</bean>
local属性和bean属性都是用力啊指定要引用的Bean的id.他们的区别在于,Spring的配置文件是可以拆分成多个的,使用local属性只能在同一个配置文件中检索Bean的id,而使用bean属性可以在其他配置文件中检索id.
3.使用内部Bean
ruguo yige Bean组件尽在移除使用,可以把它定义为内部Bean。示例代码如下:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<bean class="cn.kgc.Hobby"/>
</bean>
4.注入集合类型的属性
(1).List 对于List或数组类型的属性,可以使用<List>标签注入。示例代码如下:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="hobbies">
<list>
<value>篮球</value>
<value>乒乓球</value>
</list>
</property>
</bean>
(2).Set
对于Set类型的属性,可以使用标签注入。示例如下:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="hobbies">
<set>
<value>篮球</value>
<value>乒乓球</value>
</set>
</property>
</bean>
(3).Map
对于Map类型的属性,可以使用一下方式注入:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="hobbies">
<map>
<entry>key<value>football</value></entry>
<value>足球</value>
<entry>key<value>basketball</value></entry>
<value>篮球</value>
</map>
</property>
</bean>
(4).Properties
对于Properties类型的属性,可以使用如下注入方式:
<bean id="entityUser" class="cn.kgc.Entity.EntityUser">
<property name="hobbies">
<props>
<prop key="football" >足球</prop>
<prop key="basketBall">篮球</prop>
</props>
</property>
</bean>
2 、其他增强类(异常抛出增强、最终增强、环绕增强)
2.1异常抛出增强:
异常抛出增强的特点是在目标方法抛出异常是织入增强处理。使用异常抛出增强,可以为各功能模块提供同一个的、可以插拔的异常处理方案。
以下为异常抛出增强示例:
/**
* Desc: 异常抛出增强类
* createBy:
* Date: 2019/7/6 0006 0:59
*/
public class ErrooLogger {
private static final Logger log = Logger.getLogger(ErrooLogger.class);
//增强方法
public void afterThrowing(JoinPoint jp,RuntimeException e){
log.error(jp.getSignature().getName()+"方法执行时发生异常:"+e);
}
}
Spring.xml配置文件中的代码如下:
<!--声明异常方法所在的Bean-->
<bean id="theLogger" class="cn.kgc.util.ErrooLogger">
</bean>
<!--配置切面-->
<aop:config>
<!--定义切入点-->
<aop:pointcut id="errorPointcut" expression="execution(* cn.kgc.service.*.*(..))"/>
<!--引用包含增强方法的Bean-->
<aop:aspect ref="theLogger">
<!--将afterthrowing()方法定义为异常抛出增强并引用pointcut切入点-->
<!--通过throwing属性指定为名为e的参数注入异常实例-->
<aop:after-throwing method="afterThrowing" pointcut-ref="errorPointcut" throwing="e"/>
</aop:aspect>
</aop:config>
2.2实现最终增强
最终增强的特点是无论方法抛出异常还是正常退出,该增强都会别执行,类似于异常处理机制中的finally块的作用,一般用于释放资源。使用最终增强,就可以为各个功能模块提供统一的、可插拔方案。
示例代码如下:
/**
* Desc: 定义包含最终增强的Bean
* createBy:
* Date: 2019/7/6 0006 1:10
*/
public class AfterLogger {
private static final Logger log = Logger.getLogger(AfterLogger.class);
public void afterLogger(JoinPoint jp){
log.info(jp.getSignature().getName()+"方法执行完毕!");
}
}
Sprign配置文件中的代码:
<!--声明异常方法所在的Bean-->
<bean id="afterLogger" class="cn.kgc.util.AfterLogger">
</bean>
<!--配置切面-->
<aop:config>
<!--定义切入点-->
<aop:pointcut id="afterPointcut" expression="execution(* cn.kgc.service.*.*(..))"/>
<!--引用包含增强方法的Bean-->
<aop:aspect ref="afterLogger">
<aop:after method="afterLogger" pointcut-ref="afterPointcut"/>
</aop:aspect>
</aop:config>
2.3实现环绕增强
环绕增强是功能最强大的增强处理,Sprign把目标方法的控制权全都交给了它。环绕增强在目标方法的前后都可以植入增强处理。在环绕增强处理中,可以获取或修改目标方法的参数、返回值,可以对他进行异常处理,甚至可以决定目标方法是否被执行。
实现环绕增强代码如下:
**
* Desc:定义环绕增强类
* createBy:卢智伟
* Date: 2019/7/6 0006 1:16
*/
public class AroundLogger {
private static final Logger log = Logger.getLogger(AroundLogger.class);
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参是:" + Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed(); //执行目标方法并获得返回值
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值是:" + result);
return result;
} catch (Throwable e) {
log.error(jp.getSignature().getName() + "方法执行时发生异常:" + e);
throw e;
}
}
}
<!--声明环绕增强方法所在的Bean-->
<bean id="aroundLogger" class="cn.kgc.util.AroundLogger">
</bean>
<!--配置切面-->
<aop:config>
<!--定义切入点-->
<aop:pointcut id="afterPointcut" expression="execution(* cn.kgc.service.*.*(..))"/>
<!--引用包含增强方法的Bean-->
<aop:aspect ref="aroundLogger">
<!--将aroundLogger()方法定义为环绕增强并引用pointcut切入点-->
<aop:around method="aroundLogger" pointcut-ref="afterPointcut"/>
</aop:aspect>
</aop:config>
使用<aop:around>元素可以定义环绕增强。通过为增强方法声明ProceedingJoinPoint类型的参数,可以获得连接点信息,所用方法与JoinPoint相同。ProceedignJoinPoint是JoinPoint的子接口,其不但封装了目标方法及其入参数组,还封装了呗代理的目标对象,通过它的proceed()方法可以调用真正的目标方法,从而达到对连接点的完全控制。
总结:增强的类型
增强类型 | 描述 |
---|---|
前置增强 | 方法执行前增加处理方法 |
后置增强 | 方法执行后插入增强处理 |
异常抛出增强 | 方法发生异常时插入增强处理 |
最终增强 | 不管方法的执行状态如何都会插入增强处理 |
环绕增强 | 在方法的各个方面都插入增强,是最强大的增强处理方案 |
3、使用注解实现IoC
3.1注解定义Bean组件
Springcong 2.0版本开始引入注解的配置方式,将Bean的配置信息和Bean实现类结合在一起,进一步减少了配置文件的代码量。
我们可以在JavaBean中通过注解实现Bean组件的定义。其配置方式如下:
/**
* Desc: 用户操作接口
* createBy:卢智伟
* Date: 2019/6/30 0030 16:58
*/
@Component("userDao")
public interface UserDao {
public int addUser_UserDao(User user);
}
上述代码通过注解定义了一个名为userDao的Bean。
@Componet(“userDao”)的作用与在XML配置文件中编写<bean id = “userDao” class=“cn.kgc.dao.UserDaoImpl”/>等效。
此外还有三种特殊的注解:
注解 | 用途 |
---|---|
@Repository | 用于标注Dao类 |
@Service | 用于标注业务类 |
@Contoroller | 用于标注控制器类 |
使用特定的注解可以使组件的用途更加清晰,并且Spring在以后的版本中可能回为他们添加特殊的功能,所以推荐使用特定的注解来标注特定的实现类。
3.2 注解装配Bean组件
Spring提供了@Autowried注解来实现Bean的装配。
示例代码如下:
@Service("userService")
public class UserServiceImpl implements UserService {
/**
* 定义注解装载配件
*/
@Autowired
private UserDaoImpl userDao;
/**
* 使用@Resource注解来实现组件的装配
*/
@Resource(name="userDao")
private UserDao userDao2;
public void setUserDao2(UserDao userDao2) {
this.userDao2 = userDao2;
}
以上代码通过@Service标注了一个业务Bean,并使用@Autowired为dao属性注入所依赖的对象,spring将注解对dao属性进行复制,此时类中可以省略属性相关的setter方法。
@Autowired采用按类型匹配的方式为属性自动装配合适的依赖对象,即容器会查找和属性类型相匹配的Bean组件,并自动为属性注入。若容器中有一个以上类型匹配的Bean是,则可以使用@Qualifier指定所需的Bean名称。
@Service(“userServiceImpl”)
public class UserServiceImpl implements UserService {
/**
* 定义注解转载配件
*/
@Autowired
@Qualifier("userDao")
private UserDaoImpl userDao;
/**
* 使用@Resource注解来实现组件的装配
*/
@Resource(name="userDao")
private UserDao userDao2;
public void setUserDao2(UserDao userDao2) {
this.userDao2 = userDao2;
}
3.3 加载注解定义的Bean组件
使用注解定义完Bean组件,接下来就可以使用注解的配置信息启动Spring容器。
如何启动Spring容器:首先在Spring配置文件中添加对context命名空间的声明,然后使用<context:componet-scan>标签扫毛注解标注的类。base-package属性指定需要扫描的基准包(多个包名间用逗号隔开)。Spring会扫描这些包中的所有类,获取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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
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-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--编写配置文件,使用注解配置信息启动spring容器-->
<!--context 命名空间-component-scan命名空间的属性,base-package指定需要扫描的包,多个包用逗号隔开-->
<context:component-scan base-package="com.kgc.dao,com.kgc.service"/>
</beans>
补充:
1、@Autowired也可以对方法的入参进行标注。也可用户构造方法,实现构造注入。不过这样的用法一般比较少,这里就不做详解了。
2、使用@Autowired注解进行装配是,如果找不到相匹配的Bean组件,Spring容器就会抛出异常。此时如果依赖不是必需的,为避免抛出异常可以将required属性设置为false。如下所示:
@Autowired(required = false);
private UserDao userDao;
需要注意的是required属性默认为true,即必须找到匹配的Bean完成装配,否则抛出异常。
3、如果对类中集合类型的成员变量或方法入参使用@Autowired注解,Spring会将容器中所有和集合中元素类型匹配的Bean组件都注入进来。
3.4 使用@Resource注解实现组件装配
除了提供@Autowired注解,Spring还支持使用JSR-250(JSR全称是:Java Specification Requests,Java规范提案)中定义的@Resource注解实现组件装配,该注解也能对类的成员变量或方法入参提供注入功能。
@Resource有一个name属性,默认情况下,Spring将这个属性的值解释为要注入的Bean的名称,用法示例如下:
//为dao属性注入名为userDao的Bean
public class UserDaoImpl02 implements UserDao {
//为dao属性注入名为userDao的Bean
@Resource(name="userDao");
private UserDao userDao;
}
如果没有显示的指定Bean的名称,@Resource注解将根据字段名或者setter方法名产生默认的名称:如果注解应用于字段,将使用字段名作为Bean的名称;如果注解应用于setter方法,Bean的名称就是通过setter方法得到的属性名。
如果没有显示地指定Bean的名称,且无法找到与默认Bean名称相匹配的Bean组件,@Resource注解会有案名称查找的方式自动变为案类型匹配的方式进行装配。
4 使用注解实现AOP
4.1 认识AspectJ
AspectJ是一个面向切面的框架,它扩展了Java语言、定义了AOP语法,能够在编译期提供代码的织人,它提供了一个专门的编译器用来生成遵守字节码规范的Class文件。
Spring通过集成AspectJ实现了以注解的方式定义切面,大大减轻了配置文件的工作量。此外,因为Java的反射机制无法获取方法参数名,Spring还需要利用轻量的字节码处理框架asm(已经集成在Spring Core模块中)处理@AspectJ中所描述的方法参数名。
4.2 使用注解简化切面的配置
使用注解前需要引入相应的命名空间aop,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"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd">
</beans>
接下来使用注解定义切面,以及插入相应的增强处理:
@Aspect
public class Logger_all {
private Logger logger = Logger.getLogger(Logger_all.class);
//定义前置增强方法
@Before("execution(* main.java.cn.kgc.dao.impl.*.*(..))")
public void before(JoinPoint jp){
logger.info(("调用:"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法的入参是:"+ Arrays.toString(jp.getArgs())));
}
//定义后置增强方法
@AfterReturning(pointcut = "execution(* main.java.cn.kgc.dao.impl.*.*(..)",
returning = "result")
public void after(JoinPoint jp,Object result){
logger.info(jp.getTarget()+"类的"+jp.getSignature().getName()+"方法执行完毕,方法的返回值是:"+result);
}
}
以上各注解的作用:
注解 | 用途 |
---|---|
@Aspect | 定义切面 |
@Before | 定义前置增强方法 |
@After-Returning | 定义后置增强方法 |
下面对这些注解做一些详细的解释:
在上述示例中,使用@Aspect注解将UserServiceLogger定义为切面,并且使用@Before注解将before()方法定义为前置增强,使用@AfterRetuning注解将after()方法定义为后置增强。为了能够获取当前连接点的信息,在增强方法中添加了JoinPoint类型的参数,Spring会自动注入该实例。对于后置增强,还可以定义一个个参数用于接收该参数的名称,Spring会自动注入该实例。对于后置增强,还可以定义一个参数用于接收目标方法的返回值。需要注意的是,必须在@AfterRunting注解中通过returning属性指定该参数的名称,Spring会将目标方法的返回值赋值给指定名称的参数。
而对于相同的切入点要求,可以统一定义,以便于重用和维护。
如下所示:
@Aspect
public class Logger_all {
private Logger logger = Logger.getLogger(Logger_all.class);
@Pointcut("execution(* main.java.cn.kgc.dao.impl.*.*(..))")
public void pointcut(){}
//定义前置增强方法
@Before("pointcut()")
public void before(JoinPoint jp){
logger.info(("调用:"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法的入参是:"+ Arrays.toString(jp.getArgs())));
}
//定义后置增强方法
@AfterReturning(pointcut="pointcut()",
returning = "result")
public void after(JoinPoint jp,Object result){
logger.info(jp.getTarget()+"类的"+jp.getSignature().getName()+"方法执行完毕,方法的返回值是:"+result);
}
}
切入点表达式使用@Pointcut注解来标识,而切入点签名则需通过一个普通的方法定义来提供,如上述示例中的pointcut()方法,作为切入点签名的方法必须返回void类型,定义好切入点以后,就可以使用"pointcut()"签名进行引用。
切面定义完后,还需要在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"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p-4.0.xsd">
<!--扫描基准包中的注解-->
<context:component-scan base-package="main.java.cn.kgc"/>
<!--声明含有增强方法的Java Bean ,此处因为不需要被其他Bean引用所以不用指定id属性-->
<bean class="main.java.cn.kgc.util.Logger_all"/>
<!--启动切面的自动代理-->
<aop:aspectj-autoproxy/>
配置文件中<aop:aspectj-zuotoproxy>标签的作用:启动对于@AspectJ注解的支持,Spring将自动为匹配的Bean创建代理。
4.3 @AfterThrowing、@After和@Around注解的使用
使用@AfterThrowing注解可以定义异常抛出增强。如果需要获取抛出的异常,可以为增强方法声明相关类型的参数,并通过@AfterThrowing的Throwing属性指定该参数名称,Spring会为其注入从目标方法抛出的异常实例。
示例如下:
@Aspect
public class ErrorLogger {
Logger log = Logger.getLogger(ErrorLogger.class);
//定义异常处理方法
@AfterThrowing(pointcut = "execution(* main.java.cn.kgc.service.*.*(..))",throwing="e")
public void afterThorwing(JoinPoint jp,RuntimeException e){
log.info("执行:"+jp.getTarget()+"的:"+jp.getSignature().getName()+"时发生:"+e+"异常");
}
}
使用@After注解可以实现最终增强:
@Aspect
public class AfterLogger {
Logger logger = Logger.getLogger(AfterLogger.class);
@After("execution(* main.java.cn.kgc.service.*.*(..))")
public void afterLogger(JoinPoint jp){
logger.info(jp.getTarget()+"类的:"+jp.getSignature().getName()+"方法执行结束。");
}
}
… 使用@Around注解可以定义环绕增强。通过为增强方法声明ProceedingJoinPoint类型的参数,可以获得连接点信息。通过它的proceed()方法可以条用真正的目标方法,从而实现对连接点的完全控制。示例如下:
/**
* @description: 通过注解实现环绕增强
* @author:
* @date: 2019-07-05 11:12
*/
@Aspect
public class AroundLogger {
Logger logger = Logger.getLogger(AfterLogger.class);
@Around("execution(* main.java.cn.kgc.*.*(..))")
public Object aroundLogger(ProceedingJoinPoint pjp) throws Throwable {
//前置增强
logger.info("调用"+pjp.getTarget()+"的"+pjp.getSignature().getName()+"方法,方法入参是:"+ Arrays.toString(pjp.getArgs()));
//异常处理增强
try{
Object result = pjp.proceed(); //执行目标的方法
logger.info("执行"+pjp.getTarget()+"的"+pjp.getSignature().getName()+"方法,方法入参是:"+ Arrays.toString(pjp.getArgs())+"方法的返回值是:"+result);
//将执行的返回值返回
return result;
} catch(RuntimeException e){
logger.error(pjp.getTarget()+"的"+pjp.getSignature().getName()+"方法执行时发生异常:"+e);
throw e;
} finally {
//最终增强
logger.info(pjp.getTarget()+"的"+pjp.getSignature().getName()+"方法执行完毕。");
}
}
}
总结:
1、Spring 提供了设置注入、构造注入等依赖注入方式。
2、使用 p 命名空间可以简化属性注入的配置。
3、Spring 提供的增强处理类型包括前置增强、后置增强、异常抛出增强、环绕增强、最终增强等。
4、通过Schema 形式将 POJO 的方法配置成切面,所用标签包括:
标签 | 作用 |
---|---|
<aop:aspect> | 定义切面 |
<aop:before> | 定义前置增强处理 |
<aop:after_returning> | 定义后置增强处理 |
<aop:around> | 定义环绕增强处理 |
<aop:after-throwing> | 定义异常抛出增强处理 |
<aop:after> | 定义最终增强处理。 |
5、用来定义Bean组件的注解包括:
注解 | 用途 |
---|---|
@Component | 用于定义普通类 |
@Repository | 用于标注Dao类 |
@Service | 用于标注业务类 |
@Contoroller | 用于标注控制器类 |
使用特定的注解可以使组件的用途更加清晰,并且Spring在以后的版本中可能回为他们添加特殊的功能,所以推荐使用特定的注解来标注特定的实现类。
6、Bean组件的装配可以通过@Autowired、@Qualifier以及@Resource实现。
7、在Spring配置文件中使用<context:component-scan>元素扫描包含注解的类,来完成初始化。
8、使用注解方法定义切面可以简化配置公国,常用的注解有:
注解 | 作用 |
---|---|
@Aspect | 定义切面 |
@Before | 定义前置增强处理 |
@AfterRunting | 定义后置增强处理 |
@Around | 定义环绕增强处理 |
@AfterThrowing | 定义异常抛出增强处理 |
@After | 定义最终增强处理。 |
9、在配置文件中添加<aop:aspectj-autoproxy>元素,就可以启用对于@AspectJ注解的支持。