ioc和aop扩展
构造注入
必须提供带参的构造函数
而且配置文件的标签也是不一样的
代码语言:javascript复制public interface IUserDao {
public void add(User User);
}
public class UserDao implements IUserDao {
@Override
public void add(User User) {
System.out.println("加了一个用户对象");
}
}
public interface IUserservice {
public void addUser(User User);
}
public class UserServices implements IUserservice{
private UserDao dao;
private String s1;
private String s2;
private int i;
@Override
public void addUser(User User) {
dao.add(User);
}
public UserServices(UserDao dao, String s1, String s2, int i) {
this.dao = dao;
this.s1 = s1;
this.s2 = s2;
this.i = i;
}
public UserServices() {
}
}
public class User implements java.io.Serializable {
private Integer id; // 用户ID
private String username; // 用户名
private String password; // 密码
private String email; // 电子邮件
/* getter & setter */
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public class HelloSpringTest {
@Test
public void demo(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserservice service = (IUserservice) ctx.getBean("userService");
User user = new User();
user.setId(1);
user.setUsername("test");
user.setPassword("123456");
user.setEmail("test@xxx.com");
service.addUser(user);
}
}
代码语言:javascript复制<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="helloSpring" class="demo.HelloSpring">
<property name="who">
<value>Spring</value>
</property>
</bean>
<bean id="userDao" class="dao.impl.UserDao">
</bean>
<bean id="userService" class="service.UserServices" >
<constructor-arg>
<ref bean="userDao"/>
</constructor-arg>
<constructor-arg index="1">
<value >123</value>
</constructor-arg>
<constructor-arg index="3" type="int">
<value >123</value>
</constructor-arg>
<constructor-arg index="2">
<value >123</value>
</constructor-arg>
</bean>
<bean id="loggerUntil" class="aop.LoggerUntil"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution( public void addUser(pojo.User))"/>
<aop:aspect ref="loggerUntil">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
</aop:aspect>
</aop:config>
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>
代码语言:javascript复制<constructor-arg index="1" type="int">
参数位置和参数类型
与设值注入进行对比
设值注入
通过setter访问器实现
灵活性好,但setter方法数量较多
时效性差
通过无参构造实例化
构造注入
通过构造方法实现
灵活性差,仅靠重载限制太多
时效性好
通过匹配的构造方法实例化,但建议保留无参构造
p命名空间
特点
使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码
用法
使用前要先要在Spring配置文件中引入p命名空间
代码语言:javascript复制xmlns:p="http://www.springframework.org/schema/p"
对于直接量(基本数据类型、字符串)属性:p:属性名="属性值" 对于引用Bean的属性:p:属性名-ref="Bean的id"
代码语言:javascript复制<bean id="user" class="pojo.User" p:email="1020222@qq.com" p:id="1" p:password="123" p:username="张三">
</bean>
注入不同数据类型
类型 | 方式 |
---|---|
引用Bean | 使用<ref>标签实现 |
注意bean属性和 local 属性的区别 | |
使用内部Bean(其他地方都没法使用) | <property name="dao"> |
<bean class="dao.impl.UserDaoImpl"/></property> | |
注入集合类型的属性 | 分别使用<list>、<set>、<map>、<props>标签实现 |
注入null 和空字符串值 | 使用<null/>注入null 值 |
使用<value></value>注入空字符串值 | |
注入直接量 | 使用<value>标签实现 注意特殊字符的处理 |
<?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-3.2.xsd">
<bean id="entity" class="entity.TestEntity">
<!-- 使用<![CDATA[]]>标记处理XML特 殊字符 -->
<property name="specialCharacter1">
<value><![CDATA[P&G]]></value>
</property>
<!-- 把XML特殊字符替换为实体引用 -->
<property name="specialCharacter2">
<value>P&G</value>
</property>
<!-- 定义内部Bean -->
<property name="innerBean">
<bean class="entity.User">
<property name="username">
<value>Mr. Inner</value>
</property>
</bean>
</property>
<!-- 注入List类型 -->
<property name="list">
<list>
<!-- 定义List中的元素 -->
<value>足球</value>
<value>篮球</value>
</list>
</property>
<!-- 注入数组类型 -->
<property name="array">
<list>
<!-- 定义数组中的元素 -->
<value>足球</value>
<value>篮球</value>
</list>
</property>
<!-- 注入Set类型 -->
<property name="set">
<set>
<!-- 定义Set或数组中的元素 -->
<value>足球</value>
<value>篮球</value>
</set>
</property>
<!-- 注入Map类型 -->
<property name="map">
<map>
<!-- 定义Map中的键值对 -->
<entry>
<key>
<value>football</value>
</key>
<value>足球</value>
</entry>
<entry>
<key>
<value>basketball</value>
</key>
<value>篮球</value>
</entry>
</map>
</property>
<!-- 注入Properties类型 -->
<property name="props">
<props>
<!-- 定义Properties中的键值对 -->
<prop key="football">足球</prop>
<prop key="basketball">篮球</prop>
</props>
</property>
<!-- 注入空字符串值 -->
<property name="emptyValue">
<value></value>
</property>
<!-- 注入null值 -->
<property name="nullValue">
<null/>
</property>
</bean>
</beans>
异常抛出增强
特点
在目标方法抛出异常时织入增强处理 可拔插的异常处理方案
代码语言:javascript复制 public void throwex() throws Exception {
throw new Exception("人造异常");
}
public void afterThrowing(JoinPoint jp,Exception e){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()) e.getMessage());
//log.info("" jp.getTarget() jp.getSignature() Arrays.toString(jp.getArgs()));
}
代码语言:javascript复制<aop:config>
<aop:pointcut id="pointcut" expression="execution( public void *(..))"/>
<aop:aspect ref="loggerUntil">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
</aop:aspect>
</aop:config>
最终增强
特点
无论方法是否抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执行 类似于异常处理机制中finally块的作用,一般用于释放资源 可以为各功能模块提供统一的,可拔插的处理方案
用法与before类似
代码语言:javascript复制<aop:after>
环绕增强
目标方法前后都可织入增强处理 功能最强大的增强处理 可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方法是否执行
代码语言:javascript复制<aop:around>
代码语言:javascript复制public void around(ProceedingJoinPoint jp){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed();
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法返回值:" result);
} catch (Throwable e) {
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()) e.getMessage());
e.printStackTrace();
}finally {
System.out.println("最终");
}
}
注解实现IOC
解释
注解方式将Bean的定义信息和Bean实现类结合在一起,简化配置
@Component:实现Bean组件的定义 @Repository :用于标注DAO类 @Service :用于标注业务类 @Controller :用于标注控制器类
代码语言:javascript复制@Repository("userDao")
public class UserDaoImpl implements UserDao {
…
}
与在XML配置文件中编写
<bean id="userDao"
class="dao.impl.UserDaoImpl" />
等效
使用注意事项
要在配置文件头部加相应信息,并且开启扫描
代码语言:javascript复制<?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:p="http://www.springframework.org/schema/p"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="helloSpring" class="demo.HelloSpring">
<property name="who">
<value>Spring</value>
</property>
</bean>
<context:component-scan base-package="service,dao" />
</beans>
@Autowired
使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称
代码语言:javascript复制@Service("userService")
public class UserServices implements IUserservice{
@Autowired
private UserDao dao;
@Override
public void addUser(User User) {
dao.add(User);
}
public void throwex() throws Exception {
throw new Exception("人造异常");
}
public UserServices(UserDao dao) {
}
public UserServices() {
}
}
@Resource
注解实现组件装配,默认按名称匹配
代码语言:javascript复制@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")
private UserDao dao;
……
}
注解配置切面
@Aspect
@Pointcut
@Before
@AfterReturning
@AfterThrowing
@Around
代码语言:javascript复制@Component("loggerUntil")
@Aspect
public class LoggerUntil {
private static Logger log = Logger.getLogger(LoggerUntil.class);
@Pointcut("execution(* service.UserServices.*(..))")
public void pointcut(){};
@Before("pointcut()")
public void before(JoinPoint jp){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()));
//log.info("" jp.getTarget() jp.getSignature() Arrays.toString(jp.getArgs()));
}
@AfterReturning(pointcut = "pointcut()",returning = "result")
public void afterReturning(JoinPoint jp,Object result){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法返回值:" result);
//log.info("" jp.getTarget() jp.getSignature() result);
}
@AfterThrowing(pointcut = "pointcut()",throwing = "e")
public void afterThrowing(JoinPoint jp,Exception e){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()) e.getMessage());
//log.info("" jp.getTarget() jp.getSignature() Arrays.toString(jp.getArgs()));
}
@Around("pointcut()")
public void around(ProceedingJoinPoint jp){
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed();
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法返回值:" result);
} catch (Throwable e) {
System.out.println("调用 " jp.getTarget() " 的 " jp.getSignature().getName()
" 方法。方法入参:" Arrays.toString(jp.getArgs()) e.getMessage());
e.printStackTrace();
}finally {
System.out.println("最终");
}
}
}
代码语言:javascript复制<?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:p="http://www.springframework.org/schema/p"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="helloSpring" class="demo.HelloSpring">
<property name="who">
<value>Spring</value>
</property>
</bean>
<context:component-scan base-package="service,dao,aop" />
<aop:aspectj-autoproxy />
</beans>