初学spring,还是感觉东西有点杂的,难度不大就是有点碎,还是记录一下吧。
1. 依赖注入
- 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:context="http://www.springframework.org/schema/context"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
这是先引入的命名空间, 文件命名为applicationContext.xml。
如果我要在spring容器注册一个bean,则可以在applicationContext里加入以下代码
<bean id="user" class="com.kjy.domain.User" scope="prototype">
<!--普通属性-->
<property name="username" value="kang"/>
<property name="age" value="23"/>
<!--list 集合属性-->
<property name="habits">
<list>
<value>eat</value>
<value>sleep</value>
<value>code</value>
</list>
</property>
<!--map 集合属性-->
<property name="map">
<map>
<entry key="1" value="A"/>
<entry key="2" value="B"/>
<entry key="3" value="C"/>
</map>
</property>
</bean>
此时相应类(com.kjy.domain.User)要有相应的setter方法(setUsername,setAge,setHabits等等),其中list和map里面的元素也可以是复杂数据类型、一些自定义的类的实例等等,标签变为相应的-ref就行。这里scope的取值是多例的意思,相应的"singleton"是单例的意思,不写就默认单例。
<bean id="person" class="com.kjy.demo.Person" scope="prototype">
<constructor-arg name="username" value="sun"/>
<constructor-arg name="age" value="32"/>
</bean>
这是构造方法依赖注入。和setter方法相似,constructor-arg代替property,需要注意的是,这里name属性的取值是构造方法的形参的意思。
类似的,我们可以写出数据源的实例化代码:
<context:property-placeholder location="classpath:druid.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="maxActive" value="${maxActive}"/>
<property name="maxWait" value="${maxWait}"/>
<property name="initialSize" value="${initialSize}"/>
</bean>
- 注解方式(推荐)
比较先进的做法(也是比较快速方便的写法)就是使用注解,首先在applicationContext文件里加入:
<!--扫描指定包下所有类并筛选出特定注解的类注册为bean添加到容器中-->
<context:component-scan base-package="com.kjy"/>
然后以UserService为例:
//注册(Service代表这是服务层的类,其他可选注解有Reposity,Controller,Component等,代表不同语义)
@Service("userService")
//单例(默认)
@Scope("singleton")
public class UserServiceImpl implements UserService {
//下面注解的意思是从spring容器中匹配符合筛选条件的bean注入成员变量
/*
@Autowired //代表按类型注入
@Qualifier("userDao") //代表按名称注入
*/
@Resource //相当于上面两个注解的作用
private UserDao userDao;
@Value("value") //普通数据类型
private String string;
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
}
发现对于非自定义的类,这种方式似乎失效。这里可以扩展一下,对于非自定义的类,我们也可以采用注解的方式,以DruidDataSource为例:
@Configuration //表明这是配置类
@ComponentScan("com.kjy") //指定扫描包
@Import({DataSourceConfig.class}) //导入其他部分的配置类
public class SpringConfig {
}
@PropertySource("classpath:druid.properties") //指定配置文件
public class DataSourceConfig {
@Value("${username}")
private String username;
@Value("${password}")
private String password;
@Value("${url}")
private String url;
@Value("${driverClassName}")
private String driverClassName;
@Value("${maxActive}")
private String maxActive;
@Value("${maxWait}")
private String maxWait;
@Value("${initialSize}")
private String initialSize;
@Bean("dataSource")
public DataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setMaxActive(Integer.valueOf(maxActive));
dataSource.setMaxWait(Integer.valueOf(maxWait));
dataSource.setInitialSize(Integer.valueOf(initialSize));
return dataSource;
}
}
2. AOP
AOP就是面向切面编程,是面向对象编程的衍生,其核心是通过动态代理的方式增强对象的某些方法。
同样,也可以分为xml方式和注解方式。
- xml
这是一个简单的例子:
<bean id="target" class="com.kjy.aop.Target"/>
<bean id="aspect" class="com.kjy.aop.MyAspect"/>
<aop:config>
<aop:aspect ref="aspect">
<!--
<aop:before method="before" pointcut="execution(public void com.kjy.aop.Target.method())">
-->
<aop:pointcut id="myPointcut" expression="execution(public void com.kjy.aop.Target.method())"/>
<aop:before method="before" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
这里,Aspect为切面类,Target.method()方法是切点。切面类中的方法是为切点服务的(切点+切面类的方法=增强方法),实现动态代理。
除了<aop:before/>
标签以外,还有<aop:after-returnning>
,<aop:after>
等等标签,分别代表不同的添加位置。
- 注解(推荐)
注解可以简化配置xml文件的繁琐过程,仍以上文为例:
@Component("target")
public class Target implements TargetInterface {
@Override
public void method(){
System.out.println("original method...");
}
}
@Component("myAspect")
@Aspect //表示这是一个切面类
public class MyAspect {
@AfterReturning("execution(public void com.kjy.aop.Target.method())")
public void afterReturn(){
System.out.println("this is afterReturn operation...");
}
@Around("execution(* com.kjy.aop.Target.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("前置增强...");
Object obj = pjp.proceed();
System.out.println("后置增强...");
return obj;
}
}
这里要注意需要在applicationContext.xml文件加入这样一行:
<aop:aspectj-autoproxy/>
3. Junit
Junit的基本用法:
import org.junit.Test;
public class AopTest {
@Test
public void test(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
TargetInterface target = app.getBean("target");
app.method();
}
}
发现每次写测试方法的时候都要先获取具体对象才能测试其方法,感觉有点麻烦。
此时可以采用下面这种写法:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Resource(name = "target")
private TargetInterface target;
@Test
public void test(){
target.method();
}
}
暂时写到这里吧,其实好多内容写的太粗略没有展开,还是因为我太懒了。