public class HelloWorld {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public HelloWorld(String age) {
super();
this.age = age;
}
@Override
public String toString() {
return "HelloWorld [name=" + name + ", age=" + age + "]";
}
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld bean = context.getBean("helloWorld",HelloWorld.class);
System.out.println(bean);
}
}
root
123456
jdbc
driverclass
可参考
bean.properties
name=huzd
applicationContext.xml
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("before");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("after");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
public class StaticCarFactory {
private static Map cars = new HashMap();
static {
cars.put("car", new Car(1000));
}
public static Car getCar(String name) {
return cars.get(name);
}
}
public class InstanceFactory {
private Map cars = null;
public InstanceFactory() {
cars = new HashMap();
cars.put("car", new Car(2000));
}
public Car getCar(String name) {
return cars.get(name);
}
}
public class CarFactoryBean implements FactoryBean {
@Override
public Car getObject() throws Exception {
return new Car(3000);
}
@Override
public Class> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
通过默认类名第一个字母小写的方式获取或者使用注解的value属性配置
如下:配置repository的UserDaoImpl类可以通过userDaoImpl获取
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("save");
}
}
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
UserDaoImpl userDaoImpl = context.getBean("userDaoImpl",UserDaoImpl.class);
userDaoImpl.add();
}
}
或者通过使用value属性来配置
@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("save");
}
}
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
UserDaoImpl userDaoImpl = context.getBean("userDao",UserDaoImpl.class);
userDaoImpl.add();
}
}
在context:component-scan
内部配置子标签context:exclude-filter
context:component
中配置use-default-filters="false"
,可以理解成,默认配置为true是扫描用的默认过滤器扫描包下所有文件,配置context:exclude-filter
标签会从所有文件中过滤掉某些文件(交集),但是context:include-filter
会扫描某些文件(并集),最终得到的跟还是所有文件都扫描,所以需要关掉默认过滤器才有效果;
UserServiceImpl类
@Service
public class UserServiceImpl implements UserService {
UserDao UserDao;
@Override
public void add() {
UserDao.add();
}
}
UserServiceImpl2
@Service
public class UserServiceImpl2 implements UserService {
UserDao UserDao;
@Override
public void add() {
UserDao.add();
}
}
直接装配时,先byType会找到两个userService接口的类,再byName还是会找到userServiceImpl跟userServiceImpl2两个类(默认以类名第一个字母小写作为id),这样的话会报错,可以使用Qualifier注解将userServiceImpl微调成userService注入
@Controller
public class UserController {
@Autowired
@Qualifier("userServiceImpl")
UserService userService;
public void execute() {
userService.add();
}
}
使用在方法中就是参数前微调
@Controller
public class UserController {
UserService userService;
@Autowired
public void setUserService(@Qualifier("userServiceImpl") UserService userService) {
this.userService = userService;
}
public void execute() {
userService.add();
}
}
父类service泛型类引用BaseRepository泛型父类
public class BaseService {
@Autowired
protected BaseRepository repository;
public void add() {
System.out.println("add");
System.out.println(repository);
}
}
父类BaseRepository泛型类
public class BaseRepository {
}
具体UserService 类继承BaseService并设置泛型为User
@Service
public class UserService extends BaseService {
}
具体UserRepository 继承BaseRepository并设置泛型为User,此时UserService 就自动依赖上了UserRepository
@Repository
public class UserRepository extends BaseRepository {
}
若还有另外一个也是设置User泛型,则会报错;
@Repository
public class UserRepository2 extends BaseRepository{
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void save(User u) {
System.out.println("save user");
userDao.add(u);
}
public void add(User u) {
System.out.println("add User....");
}
}
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void add(User u) {
System.out.println("add User....");
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(public void com.huzd.study01.aop.UserService.*(User))")
public void beforeAdd(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("before add...");
}
}
在UserService的save方法执行之前执行beforeAdd方法
@Before("execution(public void com.huzd.study01.aop.UserService.save(User))")
public void beforeAdd(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("before add...");
}
在UserService的save方法执行之后执行afterAdd方法
@Aspect
@Component
public class LoggingAspect {
@After("execution(public void com.huzd.study01.aop.UserService.save(User))")
public void afterAdd(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("after add...");
}
}
在UserService的save方法抛出异常之后执行,需要注意的是,如果异常被捕获,则不会执行;
@Aspect
@Component
public class LoggingAspect {
@AfterThrowing("execution(public void com.huzd.study01.aop.UserService.save(User))")
public void beforeAdd(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("after add...");
}
}
无论连接点是正常返回还是异常返回,后置通知都会执行,如果指向让正常返回才执行,可以用返回通知代替后置通知,在注解中通过设置returning = "result"还可以获取返回值
@Aspect
@Component
public class LoggingAspect {
//@AfterThrowing("execution(public void com.huzd.study01.aop.UserService.save(User))")
//@After("execution(public void com.huzd.study01.aop.UserService.save(User))")
@AfterReturning(value = "execution(public String com.huzd.study01.aop.UserService.save(User))",returning = "result")
public void afterAdd(JoinPoint joinpoint,Object result) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("after add...");
System.out.println("result:"+result);
}
}
其实就是类似动态代理,连接点必须有ProceedingJoinPoint 参数,并且需要调用proeed方法
@Around(value = "execution(public String com.huzd.study01.aop.UserService.save(User))")
public Object around(ProceedingJoinPoint pjd) throws Throwable {
Object proceed = null;
try {
System.out.println("前置通知");
proceed = pjd.proceed();
System.out.println(1/0);
System.out.println("返回通知");
} catch (Exception e) {
System.out.println("异常通知");
}
System.out.println("后置通知");
return proceed;
}
因为AOP是利用的动态代理来实现,因此几种通知相当于在invoke中如下位置:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result = null;
try {
//前置通知
result = method.invoke(userDao, args);
//返回通知
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
//异常通知
}
//后置通知
return result;
}
execution(* *.*.*(. .)
)
第一个*
表示任意修饰符跟任意返回值
第二个*
表示任意包
第三个*
表示任意类
第四个*
表示任意方法
最后括号表示方法,中间的..
表示任意参数
execution(public void com.huzd.study01.aop.UserService.save(User))
execution(public void com.huzd.study01.aop.UserService.save(..))
execution(public void com.huzd.study01.aop.UserService.*(..))
execution(public void com.huzd.study01.aop.*.*(..))
execution(* com.huzd.study01.aop.*.*(..))
execution(* *.*.*(..))
execution(* *.*.*(Int,..))
execution(* *.*.*(..)) || execution(* *.*.*(..))
在class上实现Ordered接口或者使用@Order注解,getOrder()返回值或者是@Order的值越小则优先级越高;
在切面中声明通知方法时,一个切点表达式可能会出现在多个通知中,使用@PointCut来将一个切点声明为普通方法,该方法通常是空的,因为将切点的定义与逻辑混淆是不合理的;
将切点的定义定义成pointCut普通方法,方法可以由pointCut属性指定也可以由value属性指定,如果切点定义不在本类中,需要指定包名跟类名,例如com.huzd.study01.aop.LoggingAspect.getPointCut()
@Aspect
@Component
public class LoggingAspect {
//@AfterThrowing("execution(public void com.huzd.study01.aop.UserService.save(User))")
//@After("execution(public void com.huzd.study01.aop.UserService.save(User))")
@AfterReturning( pointcut = "com.huzd.study01.aop.LoggingAspect.getPointCut()",returning = "result")
public void afterAdd(JoinPoint joinpoint,Object result) {
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
System.out.println("methodName:"+methodName);
System.out.println("args:"+Arrays.asList(args));
System.out.println("after add...");
System.out.println("result:"+result);
}
//@Around("getPointCut()")
public Object around(ProceedingJoinPoint pjd) throws Throwable {
Object proceed = null;
try {
System.out.println("前置通知");
proceed = pjd.proceed();
System.out.println(1/0);
System.out.println("返回通知");
} catch (Exception e) {
System.out.println("异常通知");
}
System.out.println("后置通知");
return proceed;
}
@Pointcut(value = "execution(public String com.huzd.study01.aop.UserService.save(User))")
public void getPointCut() {}
}
声明式事务有两种,基于xml跟基于注解
由于springAOP是基于代理的方法,所以只能增强公共方法,因此只有公共方法才能通过springAOP进行事务管理
基于注解:@Transactional(propagation=XXX)
基于xml:
默认情况下,只有未检查异常会导致事务回滚,而受检查的不会,因此受检查异常需要自己捕获并重新抛出运行时异常,也可以使用rollbackFor或者noRollbackFor属性来定义
rollbackFor:遇到异常回滚
noRollbackFor:遇到异常不会滚;