68 Spring IoC 和AOP的扩展
IoC:控制反转
对象的生命周期管理交给了Spring,对象的属性的注入(DI)也交给Spring来管理。(IoC容器/Sping容器 ->面向bean编程)
AOP:面向切面编程
在不改变原有代码的基础上,采用代理机制动态在程序运行过程中添加一系列的概念(将公共的功能集中到一起)。
1. 掌握不同的依赖注入方式(DI-IoC)
1.1 掌握设值注入(最重要)-不同数据类型。
设值注入。这是我们在Spring应用最多且最广的一种依赖注入方式,非常符合我们以前的开发习惯,基于setter方法来实现依赖注入。
(setter强烈推荐你别自己写,让工具帮你生成!)
<!-- TestEntity bean组件 -->
<bean id="testEntity" class="cn.kgc.demo1.TestEntity">
<!-- 特殊字符值1 -->
<property name="specialCharacter1" value="1<2"></property>
<!-- 特殊字符2 -->
<property name="specialCharacter2">
<value><![CDATA[2<1]]></value>
</property>
<!-- 外部bean引入 -->
<!-- <property name="innerBean" ref="user"></property> -->
<!-- 内部bean引入(只能被使用一次 没有id) -->
<property name="innerBean">
<bean class="cn.kgc.demo1.User">
<property name="username" value="小程"></property>
</bean>
</property>
<!-- 集合类型 -->
<property name="sportList">
<list>
<value>游泳</value>
<value>下棋</value>
</list>
</property>
<!-- 数组 -->
<property name="array">
<array>
<value>下棋</value>
<value>游泳</value>
</array>
</property>
<!-- set集合 -->
<property name="set">
<set>
<value>唱跳</value>
<value>RAP</value>
</set>
</property>
<!-- map集合 -->
<property name="map">
<map>
<entry>
<key>
<value>CN</value>
</key>
<value>中华</value>
</entry>
</map>
</property>
<!-- Properties类型 -->
<property name="props">
<props>
<prop key="US">美国</prop>
</props>
</property>
<!-- 空字符串 -->
<property name="emptyValue" value=""></property>
<!-- null值 -->
<!-- <property name="nullValue" value="null"></property> -->
<property name="nullValue">
<null/>
</property>
</bean>
1.2 掌握构造注入
基于构造方法(带参构造)实现注入!
之前的设值注入使用的是无参构造(默认调用)
public class UserService {
private String username;
private User user;
private int age;
// 兼容类型的冲突问题 例如:12既可以存储为字符串 也可以存储为数值
// 出现兼容性问题时 它会按照构造参数上的顺序进行赋值
public UserService(User user,String username,int age) {
this.user = user;
this.username = username;
this.age = age;
}
// 多个不同类型参数的构造方法
/*public UserService(User user,String username) {
this.user = user;
this.username = username;
}*/
// 单个参数构造方法
/*public UserService(String username) {
this.username = username;
}*/
public UserService() {
}
public void test() {
System.out.println("用户名为:"+username);
System.out.println("用户年龄为:"+age);
System.out.println("User的用户名为:"+user.getUsername());
}
}
<bean id="userService" class="cn.kgc.demo2.UserService">
<!-- 下面的index type name属性了解即可 -->
<!-- <constructor-arg value="12" index="2"/> -->
<!-- <constructor-arg value="12" type="int"/> -->
<constructor-arg value="12" name="age"/>
<constructor-arg value="小明"/>
<constructor-arg ref="user"/>
</bean>
<!-- <bean id="userService" class="cn.kgc.demo2.UserService">
构造注入:多个不同类型参数的构造方法
<constructor-arg value="小明"/>
<constructor-arg ref="user"/>
</bean> -->
<bean id="user" class="cn.kgc.demo2.User">
<property name="username" value="小明"></property>
</bean>
<!-- <bean id="userService" class="cn.kgc.demo2.UserService">
构造注入:单个参数构造方法
<constructor-arg value="小明"/>
</bean> -->
1.3 掌握p命名空间注入
p命名空间注入它是基于设值注入,写法上简洁一些。
xmlns:p="www.springframework.org/schema/p "
<bean id="userService" class="cn.kgc.demo3.UserService" p:username="小明" p:userref="user"/>
2,掌握更多的增强处理的类型(AOP)
前置增强
后置增强
异常抛出增强
// 异常抛出增强 当异常出现之后 会执行的增强
public void throwsExceptionMethod(JoinPoint jp,Exception e) {
Signature signature = jp.getSignature();
// 获取方法名
String methodName = signature.getName();
logger.error("<=="+methodName+"方法执行出现异常<==异常信息为:"+e);
}
<aop:after-throwing method="throwssExceptionMethod" throwing="e" pointcutref="logPointCut"/>
最终增强
// 最终增强 finally执行内容
public void afterMethod(JoinPoint jp) {
Signature signature = jp.getSignature();
// 获取方法名
String methodName = signature.getName();
logger.error("<=="+methodName+"方法正在执行最终处理内容");
}
<aop:after method="afterMethod" pointcut-ref="logPointCut"/>
环绕增强:上述所有的增强整合
// 环绕增强
public Object aroundMethod(ProceedingJoinPoint jp) {
Signature signature = jp.getSignature();
String methodName = signature.getName();
String argStr = Arrays.toString(jp.getArgs());
// 前置增强
logger.info("==>正在执行"+methodName+"方法==>方法参数为:"+argStr);
// 此返回值要对应上对应的方法的返回值类型
Object returnResult = null;
try {
// 执行目标方法
returnResult = jp.proceed();
// 后置增强
logger.info("<=="+methodName+"方法执行结束<==方法返回值为:"+returnResult);
} catch (Throwable e) {
e.printStackTrace();
// 异常抛出增强
logger.error("<=="+methodName+"方法执行出现异常<==异常信息为:"+e);
}finally {
// 最终增强
logger.error("<=="+methodName+"方法正在执行最终处理内容");
}
return returnResult;
}
<aop:around method="aroundMethod" pointcut-ref="logPointCut"/>
3. 掌握注解实现IoC和AOP
XML(更接近于基础实现) ->XML+注解 -> 纯注解
3.1 实现IoC
以下注解能帮你实现自动生成bean:(IoC)
@Controller 表现层
@Service 业务逻辑层
@Repository 数据访问层
@Component 组件/部件(适合于非非三层架构的类)通用的
以下注解可以实现自动依赖:(DI)
@Autowired 适合于对象属性注入 它和Resource都可以实现按照名称和类型来注入(自动查找)
@Resource 适合于对象属性注入
@Value 适合普通值注入
3.2 实现AOP
@Component // <bean id="loggerIncreseClass" class="cn.kgc.demo4.increse.LoggerIncreseClass"/>
@Aspect // <aop:aspect ref="loggerIncreseClass">
public class LoggerIncreseClass {
private Logger logger = Logger.getLogger(LoggerIncreseClass.class);
@Pointcut("execution(* cn.kgc.demo6.UserService.*(..))")
public void pointCut() {};
// 环绕增强
// @Around("execution(* cn.kgc.demo6.UserService.*(..))")
@Around("pointCut()")
public Object aroundMethod(ProceedingJoinPoint jp) {
Signature signature = jp.getSignature();
String methodName = signature.getName();
String argStr = Arrays.toString(jp.getArgs());
// 前置增强
logger.info("==>正在执行"+methodName+"方法==>方法参数为:"+argStr);
// 此返回值要对应上对应的方法的返回值类型
Object returnResult = null;
try {
// 执行目标方法
returnResult = jp.proceed();
// 后置增强
logger.info("<=="+methodName+"方法执行结束<==方法返回值为:"+returnResult);
} catch (Throwable e) {
e.printStackTrace();
// 异常抛出增强
logger.error("<=="+methodName+"方法执行出现异常<==异常信息为:"+e);
}finally {
// 最终增强
logger.error("<=="+methodName+"方法正在执行最终处理内容");
}
return returnResult;
}
}
<!启用AOP注解-->
<aop:aspectj-autoproxy></aop:aspectj-autoprosy>